diff --git a/.devcontainer/build_gpu/devcontainer.json b/.devcontainer/build_gpu/devcontainer.json index b74cb231c4a78..4b17ee538962c 100644 --- a/.devcontainer/build_gpu/devcontainer.json +++ b/.devcontainer/build_gpu/devcontainer.json @@ -5,7 +5,7 @@ "dockerfile": "../../docker/DockerfileGPU", "context": "../..", "args": { - "IMAGE_NAME": "unifyai/ivy", + "IMAGE_NAME": "transpileai/ivy", "IMAGE_TAG": "latest-gpu" } }, diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 29f16ac1112d7..88123dae5dc3d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,7 +1,7 @@ { "name": "Ivy Development Environment (image)", - "image": "unifyai/ivy:latest", + "image": "transpileai/ivy:latest", "customizations": { "vscode": { "extensions": [ @@ -17,7 +17,7 @@ "post_create": "bash .devcontainer/post_create_commands.sh", "bashrc": "echo \"alias python=python3\" >> ~/.bashrc" }, - "initializeCommand": "docker pull unifyai/ivy:latest", + "initializeCommand": "docker pull transpileai/ivy:latest", // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], diff --git a/.devcontainer/image_gpu/devcontainer.json b/.devcontainer/image_gpu/devcontainer.json index ca899e132de7b..1869260fb7645 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/ivy:latest-gpu", + "image": "transpileai/ivy:latest-gpu", "customizations": { "vscode": { "extensions": [ @@ -19,7 +19,7 @@ "post_create": "bash .devcontainer/post_create_commands.sh", "bashrc": "echo \"alias python=python3\" >> ~/.bashrc" }, - "initializeCommand": "docker pull unifyai/ivy:latest", + "initializeCommand": "docker pull transpileai/ivy:latest", // Use 'forwardPorts' to make a list of ports inside the container available locally. // "forwardPorts": [], diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index f24fc1e04f944..9ff8c778e98cd 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,21 +1,21 @@ # Ivy Framework -ivy/func_wrapper.py @VedPatwardhan -**/gradients.py @VedPatwardhan -ivy/utils/backend @VedPatwardhan @CatB1t -ivy/utils/backend/ast_helpers.py @CatB1t +ivy/func_wrapper.py @Sam-Armstrong +**/gradients.py @Sam-Armstrong +ivy/utils/backend @Sam-Armstrong +ivy/utils/backend/ast_helpers.py @Sam-Armstrong # Ivy Testing -ivy_tests/test_ivy/helpers/ @CatB1t +ivy_tests/test_ivy/helpers/ @Sam-Armstrong # Docs builder -docs/index.rst @KareemMAX -docs/make_docs.sh @KareemMAX -docs/partial_conf.py @KareemMAX -docs/prebuild.sh @KareemMAX -docs/overview/contributing/building_the_docs.rst @KareemMAX -docs/overview/deep_dive/building_the_docs_pipeline.rst @KareemMAX -docs/_templates @KareemMAX -docs/demos @KareemMAX +docs/index.rst @Sam-Armstrong +docs/make_docs.sh @Sam-Armstrong +docs/partial_conf.py @Sam-Armstrong +docs/prebuild.sh @Sam-Armstrong +docs/overview/contributing/building_the_docs.rst @Sam-Armstrong +docs/overview/deep_dive/building_the_docs_pipeline.rst @Sam-Armstrong +docs/_templates @Sam-Armstrong +docs/demos @Sam-Armstrong # README -README.md @guillesanbri +README.md @Sam-Armstrong 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 254fb28e548a0..0cda22fa3af37 100644 --- a/.github/workflows/array-api-det-coverage.yml +++ b/.github/workflows/array-api-det-coverage.yml @@ -1,8 +1,8 @@ name: array-api-determine-test-coverage on: workflow_dispatch: - schedule: - - cron: "30 20 * * 6" +# schedule: +# - cron: "30 20 * * 6" permissions: actions: read diff --git a/.github/workflows/array-api-intelligent-tests-pr.yml b/.github/workflows/array-api-intelligent-tests-pr.yml deleted file mode 100644 index 2bb007f86ba61..0000000000000 --- a/.github/workflows/array-api-intelligent-tests-pr.yml +++ /dev/null @@ -1,85 +0,0 @@ -name: array-api-intelligent-tests-pr -on: - pull_request: - types: [ labeled, 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@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 - - - 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${{ 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: 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' - run: exit 1 diff --git a/.github/workflows/array-api-intelligent-tests.yml b/.github/workflows/array-api-intelligent-tests.yml deleted file mode 100644 index 576bbe9475e16..0000000000000 --- a/.github/workflows/array-api-intelligent-tests.yml +++ /dev/null @@ -1,82 +0,0 @@ -name: array-api-intelligent-tests -on: - workflow_dispatch: - push: - branches: - - 'main' -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@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 - - - name: Get Job URL - uses: Tiryoh/gha-jobid-action@v0 - id: jobs - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - job_name: ${{ github.job }} - - - name: Update Mapping and Determine Tests - env: - SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} - run: | - 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 ${{ matrix.branch }} - cd .. - cp ivy/tests.pbz2 Mapping/ - cd Mapping - git add . - git commit -m "Update Mapping" - git push origin main${{ matrix.branch }} - continue-on-error: true - - - name: Run Tests - id: tests - run: | - cd ivy - 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/assign-pr.yml b/.github/workflows/assign-pr.yml new file mode 100644 index 0000000000000..9416d25ae514b --- /dev/null +++ b/.github/workflows/assign-pr.yml @@ -0,0 +1,24 @@ +name: assign-pr + +on: + pull_request: + types: [opened] + +jobs: + assign: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Assign PR + env: + GITHUB_TOKEN: ${{ secrets.DEV_BOT_GENERAL_PAT }} + run: | + PR_NUMBER=$(jq --raw-output .pull_request.number "$GITHUB_EVENT_PATH") + curl -s -X POST \ + -H "Authorization: token $GITHUB_TOKEN" \ + -H "Accept: application/vnd.github.v3+json" \ + https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/assignees \ + -d '{"assignees":["Sam-Armstrong"]}' diff --git a/.github/workflows/binaries.yml b/.github/workflows/binaries.yml index 51dd639e700d0..6d8a93c96e09c 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 + repository: ivy-llc/binaries + token: ${{ secrets.DEV_BOT_GENERAL_PAT }} path: binaries - persist-credentials: false - name: Add Tag to Binaries run: | diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml new file mode 100644 index 0000000000000..9cbd515e0f183 --- /dev/null +++ b/.github/workflows/build-docs.yml @@ -0,0 +1,75 @@ +name: Update docs +on: + workflow_call: + inputs: + package-dependencies: + description: 'Apt package dependencies' + required: false + default: '' + type: string + repo-name: + description: 'Repo display name in the URL' + required: false + default: '' + type: string + docs-repo: + description: 'Repo to hold the docs' + required: false + default: ivy-llc/docs + type: string + +permissions: + contents: write + +jobs: + publish-dev-docs: + name: Publish dev docs + uses: ./.github/workflows/publish-docs.yml + secrets: inherit + concurrency: + group: dev-docs + cancel-in-progress: true + with: + package-dependencies: ${{ inputs.package-dependencies }} + repo-name: ${{ inputs.repo-name }} + docs-repo: ${{ inputs.docs-repo }} + + publish-release-docs: + name: Publish release docs + needs: publish-dev-docs + uses: ./.github/workflows/publish-docs.yml + if: always() && startsWith(github.ref, 'refs/tags') + secrets: inherit + with: + version: ${{ github.ref_name }} + package-dependencies: ${{ inputs.package-dependencies }} + repo-name: ${{ inputs.repo-name }} + docs-repo: ${{ inputs.docs-repo }} + + update-versions: + name: Update versions.json + needs: publish-release-docs + runs-on: ubuntu-latest + steps: + - name: Checkout πŸ›ŽοΈ Docs + uses: actions/checkout@v4 + with: + repository: ${{ inputs.docs-repo }} + token: ${{ secrets.DEV_BOT_PAT }} + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Add version to ${{ inputs.repo-name }}.json + run: | + python versions/add_version.py ${{ inputs.repo-name }} ${{ github.ref_name }} + + - name: Commit and push + run: | + git config --global user.email "hello@transpile-ai.com" + git config --global user.name "ivy-dev-bot" + git add versions/ + git commit -m "Add ${{ github.ref_name }} to ${{ inputs.repo-name }}.json" + git push diff --git a/.github/workflows/test-ivy-cron.yml b/.github/workflows/commit-tests.yml similarity index 51% rename from .github/workflows/test-ivy-cron.yml rename to .github/workflows/commit-tests.yml index 8e9e62f3faf35..ef7599f0d20a5 100644 --- a/.github/workflows/test-ivy-cron.yml +++ b/.github/workflows/commit-tests.yml @@ -1,25 +1,41 @@ -name: test-ivy-cron +name: tests on: - workflow_dispatch: - schedule: - - cron: '30 * * * *' + push: + branches: + - main + pull_request: + branches: + - main + permissions: actions: read jobs: - run-nightly-tests: + relevant-tests: runs-on: ubuntu-latest steps: - - name: Checkout πŸ›ŽοΈIvy - uses: actions/checkout@v2 + - name: Checkout Ivy πŸ›Ž + uses: actions/checkout@v3 with: path: ivy persist-credentials: false - submodules: "recursive" + fetch-depth: 100 + + - name: Fetch Commit Changes + id: fetch_changes + run: | + cd ivy + if [ "${{ github.event_name }}" == "pull_request" ]; then + git fetch origin main + git diff origin/main HEAD --output="commit-diff.txt" + else + git diff HEAD^ HEAD --output="commit-diff.txt" + fi + - 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 @@ -35,10 +51,9 @@ jobs: - name: Run Tests id: tests run: | - cd ivy pip3 install pymongo - python scripts/setup_tests/cron_tests.py ${{ github.run_number }} false - 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 }} + cd ivy + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest python3 scripts/run_tests_from_diff.py continue-on-error: true - name: Check on failures diff --git a/.github/workflows/det-test-coverage.yml b/.github/workflows/det-test-coverage.yml index be26581eb0903..a0834c58c1c1d 100644 --- a/.github/workflows/det-test-coverage.yml +++ b/.github/workflows/det-test-coverage.yml @@ -1,8 +1,8 @@ name: Determine Test Coverage on: workflow_dispatch: - schedule: - - cron: "30 20 * * 6" +# schedule: +# - cron: "30 20 * * 6" permissions: actions: read diff --git a/.github/workflows/dockerfile-gpu-push.yml b/.github/workflows/dockerfile-gpu-push.yml index df978d2ee95a9..3bd07c2c5a966 100644 --- a/.github/workflows/dockerfile-gpu-push.yml +++ b/.github/workflows/dockerfile-gpu-push.yml @@ -8,7 +8,7 @@ on: jobs: build: - runs-on: ubuntu-latest-4-cores + runs-on: ubuntu-latest steps: - name: Checkout πŸ›Ž Ivy @@ -22,5 +22,5 @@ jobs: - 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 + docker build --progress=plain --no-cache -t transpileai/ivy:latest-gpu -f docker/DockerfileGPU . + docker push transpileai/ivy:latest-gpu diff --git a/.github/workflows/dockerfile-image.yml b/.github/workflows/dockerfile-image.yml index 3f82ea05ea63c..242a58332ccaa 100644 --- a/.github/workflows/dockerfile-image.yml +++ b/.github/workflows/dockerfile-image.yml @@ -1,10 +1,11 @@ name: Build Dockerfile on: + workflow_dispatch: push: branches: [ "main" ] pull_request: - types: [labeled, review_requested] + types: [review_requested] branches: [ "main" ] jobs: @@ -17,4 +18,4 @@ jobs: - uses: actions/checkout@v3 - name: Build Dockerfile run: | - docker build . --file docker/Dockerfile --tag unifyai/ivy:$(date +%s) + docker build . --file docker/Dockerfile --tag transpileai/ivy:$(date +%s) diff --git a/.github/workflows/dockerfile-multiversion-push.yml b/.github/workflows/dockerfile-multiversion-push.yml index 79920c208d7d8..3d25ebe845c49 100644 --- a/.github/workflows/dockerfile-multiversion-push.yml +++ b/.github/workflows/dockerfile-multiversion-push.yml @@ -22,5 +22,5 @@ jobs: - name: Build and push Dockerfile run: | - docker build --progress=plain --no-cache -t unifyai/multiversion:latest -f docker/DockerfileMultiversion . - docker push unifyai/multiversion:latest + docker build --progress=plain --no-cache -t transpileai/multiversion:latest -f docker/DockerfileMultiversion . + docker push transpileai/multiversion:latest diff --git a/.github/workflows/dockerfile-push.yml b/.github/workflows/dockerfile-push.yml index 3a4e9959b6847..beaf37d2d2598 100644 --- a/.github/workflows/dockerfile-push.yml +++ b/.github/workflows/dockerfile-push.yml @@ -2,8 +2,8 @@ name: Dockerfile Push on: schedule: - # run at everyday at 00:00 UTC - - cron: '0 0 * * *' + # runs everyday at 23:00 UTC + - cron: '0 23 * * *' workflow_dispatch: jobs: @@ -27,5 +27,5 @@ jobs: - name: Build and push Dockerfile run: | - docker build . --file docker/Dockerfile --tag unifyai/ivy:latest - docker push unifyai/ivy:latest + docker build . --file docker/Dockerfile --tag transpileai/ivy:latest + docker push transpileai/ivy:latest diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 7492ddc4c0c35..d463f4a498328 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,15 +1,17 @@ name: Update docs on: workflow_call: - push: - branches: - - main - tags: - - v* workflow_dispatch: + schedule: + - cron: "0 3 * * *" + +permissions: + contents: write jobs: update-docs: name: Update docs - uses: unifyai/workflows/.github/workflows/docs.yml@main + uses: ./.github/workflows/build-docs.yml secrets: inherit + with: + repo-name: '' diff --git a/.github/workflows/duplication.yml b/.github/workflows/duplication.yml index 4858881f132ef..625f0042b4be4 100644 --- a/.github/workflows/duplication.yml +++ b/.github/workflows/duplication.yml @@ -1,29 +1,29 @@ -name: duplicate-test-check +name: tests on: + push: + branches: + main pull_request: permissions: actions: read jobs: - run-check: - if: contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Ivy API Experimental') - runs-on: ubuntu-latest - steps: - - name: Checkout Ivy πŸ›Ž - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 + duplicate-tests: + runs-on: ubuntu-latest + steps: + - name: Checkout Ivy πŸ›Ž + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + fetch-depth: 100 + - name: Check Duplicate Function + id: tests + run: | + cd ivy + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest python3 scripts/duplicate.py + continue-on-error: true - - name: Check Duplicate Function - id: tests - run: | - cd ivy - docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 scripts/duplicate.py - continue-on-error: true - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 + - name: Check on failures + if: steps.tests.outcome != 'success' + run: exit 1 diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml new file mode 100644 index 0000000000000..5e8a4961bab68 --- /dev/null +++ b/.github/workflows/integration-tests.yml @@ -0,0 +1,42 @@ +name: integration-tests +on: + push: + branches: + - main + pull_request: + branches: + - main + +permissions: + actions: read +jobs: + kornia: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + target : [ jax, numpy, tensorflow ] + steps: + - name: Checkout Ivy πŸ›Ž + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + fetch-depth: 100 + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + pip3 install kornia + cd ivy + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/shell/run_integration_tests.sh kornia ${{ matrix.target }} ${{ secrets.IVY_API_KEY }} + continue-on-error: true + + - name: Check on failures + if: steps.tests.outcome != 'success' + run: exit 1 diff --git a/.github/workflows/intelligent-tests-pr.yml b/.github/workflows/intelligent-tests-pr.yml deleted file mode 100644 index 66c3af4eb79c9..0000000000000 --- a/.github/workflows/intelligent-tests-pr.yml +++ /dev/null @@ -1,125 +0,0 @@ -name: intelligent-tests-pr -on: - workflow_dispatch: - pull_request: - types: [labeled, 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: 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: Label Test Failures - run: | - 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 "The CI captured the following failing tests based on your changes:" - cat labeled_combined_failures.txt - else - echo "No test failures found based on your changes!" - fi - - 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: 100 - - - 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: 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 1 - pip install pydriller GitPython - python ivy/scripts/setup_tests/clone-mapping.py - cp Mapping/tests.pbz2 ivy/ - cd ivy - python scripts/determine_tests/determine_tests.py ${{ matrix.branch }} pr - set -o pipefail - 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 - 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: test_failures_${{ matrix.branch }} - path: ivy/test_failures_${{ matrix.branch }}.txt - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 diff --git a/.github/workflows/intelligent-tests.yml b/.github/workflows/intelligent-tests.yml deleted file mode 100644 index 261cd5fd1014f..0000000000000 --- a/.github/workflows/intelligent-tests.yml +++ /dev/null @@ -1,103 +0,0 @@ -name: intelligent-tests -on: - workflow_dispatch: - push: - branches: - - 'main' -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: 100 - - - 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: Get Job URL - uses: Tiryoh/gha-jobid-action@v0 - id: jobs - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - job_name: ${{ github.job }} - - - name: Update Mapping and Determine Tests - env: - SSH_DEPLOY_KEY: ${{ secrets.SSH_DEPLOY_KEY }} - run: | - source ./ivy/scripts/shell/clone_mapping.sh master${{ matrix.branch }} - pip install pydriller pymongo - cp Mapping/tests.pbz2 ivy/ - cd ivy - python scripts/determine_tests/determine_tests.py ${{ matrix.branch }} - cd .. - cp ivy/tests.pbz2 Mapping/ - cd Mapping - git add . - git commit -m "Update Mapping" - git push origin master${{ matrix.branch }} - continue-on-error: true - - - name: Run Tests - id: tests - 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 - 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/lint-bot.yml b/.github/workflows/lint-bot.yml deleted file mode 100644 index 52ee85c1ae2d9..0000000000000 --- a/.github/workflows/lint-bot.yml +++ /dev/null @@ -1,16 +0,0 @@ -name: lint-bot - -on: - push: - branches: - - main - workflow_dispatch: - -permissions: - contents: write - -jobs: - fix-linting: - name: Fix Linting - uses: unifyai/workflows/.github/workflows/lint-bot.yml@main - secrets: inherit diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index cfa8c518c2ead..9e7416f58026a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,16 +1,50 @@ name: lint on: - pull_request: - types: [opened, synchronize, reopened] - push: - branches: [main] + workflow_dispatch: + schedule: + - cron: "0 4 * * *" permissions: contents: write jobs: - check-formatting: - name: Check formatting - uses: unifyai/workflows/.github/workflows/lint.yml@main - secrets: inherit + lint-code: + runs-on: ubuntu-latest + steps: + - name: Checkout ${{ github.event.repository.name }} + uses: actions/checkout@v4 + + - name: Get changed files + if: github.event_name == 'pull_request' + id: changed-files + uses: lots0logs/gh-action-get-changed-files@2.1.4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Python + uses: actions/setup-python@v4 + with: + python-version: 3.10.14 + + - name: Run pre-commit + continue-on-error: true + uses: pre-commit/action@v3.0.0 + with: + extra_args: ${{ github.event_name == 'pull_request' && format('--files {0}', join(fromJSON(steps.changed-files.outputs.all), ' ')) || '--all-files' }} + + - name: Check if there are changes + id: check + run: | + if [[ -n "$(git status --porcelain)" ]]; then + echo "changes=true" >> $GITHUB_OUTPUT + fi + + - name: Commit changes + if: steps.check.outputs.changes == 'true' + run: | + git config --local user.email "hello@transpile-ai.com" + git config --local user.name "ivy-dev-bot" + git add . + git commit -m "auto-lint code" + git push diff --git a/.github/workflows/manual-tests.yml b/.github/workflows/manual-tests.yml index 819ff6cccc31e..4a4fde57d0c6b 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 @@ -75,13 +85,12 @@ jobs: with: path: ivy persist-credentials: false - submodules: "recursive" fetch-depth: 100 - 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 +108,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/pr-lint-bot.yml b/.github/workflows/pr-lint-bot.yml deleted file mode 100644 index 98d0ba04a17ac..0000000000000 --- a/.github/workflows/pr-lint-bot.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Trigger lint format - -on: - pull_request_target: - types: [opened, edited, synchronize, reopened] - -permissions: - contents: write - -jobs: - fix-linting: - name: PR Lint Bot - uses: unifyai/workflows/.github/workflows/pr-lint-bot.yml@main - secrets: inherit diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml index c7ccc919b6e61..926e60ff23a4d 100644 --- a/.github/workflows/pre-release.yml +++ b/.github/workflows/pre-release.yml @@ -1,12 +1,54 @@ 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 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 @@ -27,17 +69,25 @@ 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 + python scripts/setup_tests/setup_priority_tests.py ${{ matrix.branch }} + 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 }} + 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 }} | tee test_results_${{ matrix.branch }}.txt + continue-on-error: true - - 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 }} + - 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/publish-docs.yml b/.github/workflows/publish-docs.yml new file mode 100644 index 0000000000000..ccc0b545be46c --- /dev/null +++ b/.github/workflows/publish-docs.yml @@ -0,0 +1,96 @@ +run-name: Publish ${{ inputs.version }} docs +on: + workflow_call: + inputs: + version: + description: 'Version of the docs' + required: false + default: 'dev' + type: string + package-dependencies: + description: 'Apt package dependencies' + required: false + default: '' + type: string + repo-name: + description: 'Repo display name in the URL' + required: false + default: ${{ github.event.repository.name }} + type: string + docs-repo: + description: 'Repo to hold the docs' + required: false + default: ivy-llc/docs + type: string + +permissions: + contents: write + +jobs: + publish-docs: + runs-on: ubuntu-latest + name: Publish ${{ inputs.version }} docs + steps: + - name: Checkout πŸ›ŽοΈ ${{ inputs.repo-name }} + uses: actions/checkout@v4 + with: + fetch-depth: 0 + submodules: recursive + + - name: Checkout πŸ›ŽοΈ Doc-builder + uses: actions/checkout@v4 + with: + repository: ivy-llc/doc-builder + path: .doc-builder + + - name: Install apt dependencies + if: inputs.package-dependencies != '' + run: | + sudo apt-get update + sudo apt-get install -y ${{ inputs.package-dependencies }} + + - name: Setup Python + uses: actions/setup-python@v4 + id: setup-python + with: + python-version: '3.10' + + - name: Get cache week key + id: get-cache-week-key + run: | + echo "week-key=$(date +'%Y-%V')" >> $GITHUB_OUTPUT + + - name: Cache dependencies + uses: actions/cache@v3 + id: cache + with: + path: ./.venv + key: ${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-pip-${{ steps.get-cache-week-key.outputs.week-key }} + restore-keys: | + ${{ runner.os }}-${{ steps.setup-python.outputs.python-version }}-pip- + + - name: Create virtual environment + if: steps.cache.outputs.cache-hit != 'true' + run: | + python -m venv .venv + + - name: Build docs + run: | + source .venv/bin/activate + pip install --upgrade pip + pip install wheel setuptools + cd .doc-builder + export IVY_VERSION=${{ inputs.version }} + ./make_docs_without_docker.sh .. + + - name: Deploy to GitHub Pages + uses: JamesIves/github-pages-deploy-action@v4.6.1 + with: + folder: docs/build + target-folder: "${{ inputs.version != 'dev' && format('{0}/', inputs.version) || '' }}${{ inputs.repo-name }}" + ssh-key: ${{ secrets.DOCS_DEPLOY_KEY }} + branch: main + git-config-name: ivy-dev-bot + git-config-email: hello@transpile-ai.com + repository-name: ${{ inputs.docs-repo }} + clean: true diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f29e7b8bbf2c8..518df7a311e89 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -5,14 +5,9 @@ on: workflow_dispatch: jobs: - publish-release-docs: - name: Publish Release Docs - uses: unifyai/workflows/.github/workflows/docs.yml@main - secrets: inherit - 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 deleted file mode 100644 index 64153d06ffa31..0000000000000 --- a/.github/workflows/run-all-tests.yml +++ /dev/null @@ -1,78 +0,0 @@ -name: run-all-tests -on: - workflow_dispatch: - -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 ] - steps: - - name: Checkout Ivy πŸ›Ž - uses: actions/checkout@v3 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 100 - - - 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: Get Job URL - uses: Tiryoh/gha-jobid-action@v0 - id: jobs - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - job_name: ${{ github.job }} - - - name: Run Tests - run: | - pip3 install pymongo - 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 - 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/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..a368dde604097 100644 --- a/.github/workflows/test-docstrings.yml +++ b/.github/workflows/test-docstrings.yml @@ -1,11 +1,11 @@ -name: test-docstrings +name: tests on: push: - pull_request: - types: [labeled, opened, synchronize, reopened, review_requested] + branches: + main workflow_dispatch: jobs: - run-docstring-tests: + docstring-tests: if: ${{(github.event_name == 'push') || contains(github.event.pull_request.labels.*.name, 'Exhaustive CI') || contains(github.event.pull_request.labels.*.name, 'Function Reformatting')}} runs-on: ubuntu-latest steps: @@ -13,7 +13,6 @@ jobs: with: path: ivy persist-credentials: false - submodules: "recursive" - uses: actions/setup-python@v3 with: python-version: "3.8" @@ -21,4 +20,4 @@ jobs: - name: Run Docstring Tests run: | cd ivy - docker run --rm -i -v "$(pwd)":/ivy unifyai/ivy:latest python3 -m pytest ivy_tests/test_docstrings.py + docker run --rm -i -v "$(pwd)":/ivy transpileai/ivy:latest python3 -m pytest ivy_tests/test_docstrings.py -p no:warnings 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 deleted file mode 100644 index b4cd6719fbe58..0000000000000 --- a/.github/workflows/test-ivy-cron-gpu.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: test-ivy-cron-gpu -on: - workflow_dispatch: - 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 - uses: actions/checkout@v2 - with: - path: ivy - persist-credentials: false - submodules: "recursive" - fetch-depth: 2 - - - name: Install ivy and fetch binaries - run: | - cd ivy - export TAG="cp310-cp310-manylinux_2_17_x86_64" - 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: | - pip3 install pymongo - cd ivy - python3 scripts/setup_tests/cron_tests.py ${{ github.run_number }} true - 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 }} - - 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: 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 deleted file mode 100644 index fd36dd585d175..0000000000000 --- a/.github/workflows/test-ivy-cron-multi-version.yml +++ /dev/null @@ -1,46 +0,0 @@ -name: test-ivy-cron-multi-version -on: - workflow_dispatch: - schedule: - - cron: '20 * * * *' -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 - 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_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 }} - continue-on-error: true - - - name: Check on failures - if: steps.tests.outcome != 'success' - run: exit 1 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/update-test-dashboard.yml b/.github/workflows/update-test-dashboard.yml new file mode 100644 index 0000000000000..337b2f1862d92 --- /dev/null +++ b/.github/workflows/update-test-dashboard.yml @@ -0,0 +1,534 @@ +# Workflow to run all the tests for the ivy frontends and functional api, +# and update the remote database with the results + +name: update-test-dashboard +on: + workflow_dispatch: + schedule: + - cron: "0 0 * * *" +permissions: + actions: read +jobs: + update-frontends-torch: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ blas_and_lapack_ops, comparison_ops, creation_ops, dtype, func_wrapper, + indexing_slicing_joining_mutating_ops, linalg, miscellaneous_ops, + pointwise_ops, random_sampling, reduction_ops, special_funcs, + spectral_ops, tensor_functions, tensor, utilities ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + per_page: 64 + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_torch_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_torch_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-frontends-torch-nn-functional: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ convolution_functions, distance_functions, dropout_functions, layer_functions, + linear_functions, loss_functions, non_linear_activation_functions, norms, + pooling_functions, sparse_functions, vision_functions ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + per_page: 44 + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_torch_nn_functional_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_torch_nn_functional_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-frontends-tensorflow: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ __operators__, dtypes, func_wrapper, general_functions, linalg, math, nest, nn, + random, raw_ops, signal, tensor, tensorarray, tensorshape ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + per_page: 56 + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_tensorflow_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_tensorflow_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-frontends-tensorflow-keras: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ activations, backend ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_tensorflow_keras_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_tensorflow_keras_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-frontends-jax: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ array, func_wrapper, general_functions, random ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_jax_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_jax_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-frontends-jax-lax: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ control_flow_operators, custom_gradient_operators, linalg, operators ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_jax_lax_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_jax_lax_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-frontends-jax-nn: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ non_linear_activations ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_jax_nn_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_jax_nn_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-frontends-jax-numpy: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ creation, dtype, fft, indexing, linalg, logic, manipulations, + mathematical_functions, searching_sorting, statistical ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + per_page: 40 + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_jax_numpy_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_jax_numpy_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-frontends-numpy: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ broadcast, data_type_routines, fft, indexing_routines, linalg, logic, manipulation_routines, + mathematical_functions, matrix, ndarray, random, sorting_searching_counting, statistics, ufunc ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + per_page: 56 + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_numpy_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_numpy_frontends.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-ivy-core: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ creation, device, dtype, elementwise, general, gradients, linalg, manipulation, meta, + nest, random, searching, set, sorting, statistical, utility ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + per_page: 64 + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_ivy_core.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_ivy_core.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-ivy-experimental-core: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ creation, elementwise, general, gradients, linalg, manipulation, + random, searching, sorting, sparse_array, statistical, utility ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + per_page: 48 + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_ivy_experimental_core.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_ivy_experimental_core.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-ivy-experimental-nn: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ activations, layers, losses, norms ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_ivy_experimental_nn.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_ivy_experimental_nn.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi + + update-ivy-nn: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + submodule : [ activations, layers, losses, norms ] + backend : [ jax, numpy, tensorflow, torch ] + steps: + - name: Checkout πŸ›ŽοΈIvy + uses: actions/checkout@v3 + with: + path: ivy + persist-credentials: false + + - name: Get Job URL + uses: Tiryoh/gha-jobid-action@v0 + id: jobs + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + job_name: ${{ github.job }} (${{ matrix.submodule }}, ${{ matrix.backend }}) + + - name: Install ivy + run: | + cd ivy + sudo pip3 install -e . + + - name: Run Tests + id: tests + run: | + cd ivy + pip3 install pymongo + pip3 install pytest-json-report + echo "html_url: ${{ steps.jobs.outputs.html_url }}" + if [ "${{ steps.jobs.outputs.html_url }}" = "null" ]; then + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_ivy_nn.sh ${{ matrix.submodule }} ${{ matrix.backend }} https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + else + docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest scripts/update_test_dashboard/update_ivy_nn.sh ${{ matrix.submodule }} ${{ matrix.backend }} ${{ steps.jobs.outputs.html_url }} ${{ secrets.IVY_DASHBOARD_DB_KEY }} + fi diff --git a/.github/workflows/welcome-message.yml b/.github/workflows/welcome-message.yml deleted file mode 100644 index a41cb471ed830..0000000000000 --- a/.github/workflows/welcome-message.yml +++ /dev/null @@ -1,56 +0,0 @@ -name: Check Semantic and welcome new contributors - -on: - pull_request_target: - types: - - opened - - edited - - synchronize - - reopened - workflow_call: - -permissions: - pull-requests: write - -jobs: - pr-compliance-checks: - name: PR Compliance Checks - runs-on: ubuntu-latest - timeout-minutes: 10 - steps: - - uses: mtfoley/pr-compliance-action@v0.5.0 - with: - body-auto-close: false - protected-branch-auto-close: false - body-comment: > - ## Issue Reference - - In order to be considered for merging, the pull request description must refer to a - specific issue number. This is described in our - [contributing guide](https://unify.ai/docs/ivy/overview/contributing/the_basics.html#todo-list-issues) and our PR template. - - This check is looking for a phrase similar to: "Fixes #XYZ" or "Resolves #XYZ" where XYZ is the issue - number that this PR is meant to address. - - welcome: - name: Welcome - runs-on: ubuntu-latest - timeout-minutes: 10 - if: github.event.action == 'opened' - steps: - - uses: actions/first-interaction@v1 - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: |- - Congrats on making your first Pull Request and thanks for supporting Ivy! πŸŽ‰ - Join the conversation in our [Discord](https://discord.com/invite/sXyFF8tDtm). - - For every PR opened, we run unit tests and comment the results in the PR to ensure the functionality remains intact. - Please make sure they are passing. πŸ’ͺ - - If you want to check them from the action runners, you can open the `display_test_results` job. πŸ‘€ - It contains the following two sections: - - **Combined Test Results:** This shows the results of all the ivy tests that ran on the PR. βœ”οΈ - - **New Failures Introduced:** This lists the tests that fail on this PR. - - Keep in mind that we will assign an engineer for this task and they will look at it based on the workload that they have, **kindly be patient πŸ˜„**. 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/.gitmodules b/.gitmodules index 3f06491476bf6..9f8ee635c3bda 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,4 +4,4 @@ url = https://github.com/data-apis/array-api-tests.git [submodule "docs/demos"] path = docs/demos - url = https://github.com/unifyai/demos.git + url = https://github.com/ivy-llc/demos.git diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 470cad8c679d6..a5ce45477b4a7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,38 +1,39 @@ repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: - id: check-yaml - id: trailing-whitespace - id: check-toml - id: end-of-file-fixer + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.3.5 + hooks: + # Run the linter. + - id: ruff + args: [ --fix ] - repo: https://github.com/psf/black-pre-commit-mirror - rev: 23.11.0 + rev: 24.3.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.1 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 + - repo: https://github.com/ivy-llc/lint-hook + rev: a72ffb17562d919311653d7f593cb537d1245c19 hooks: - id: ivy-lint diff --git a/CITATION.cff b/CITATION.cff index 7472e9bf6da27..7ea5ddb7a8200 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -20,7 +20,7 @@ identifiers: - type: doi value: 10.48550/arXiv.2102.02886 description: 'arXiv preprint ' -repository-code: 'https://github.com/unifyai/ivy' +repository-code: 'https://github.com/ivy-llc/ivy' url: 'https://unify.ai/' repository: 'https://github.com/unifyai/' abstract: 'We introduce Ivy, a templated Deep Learning (DL) framework which abstracts existing DL frameworks. Ivy unifies the core functions of these frameworks to exhibit consistent call signatures, syntax and input-output behaviour. New high-level framework-agnostic functions and classes, which are usable alongside framework-specific code, can then be implemented as compositions of the unified low-level Ivy functions. Ivy currently supports TensorFlow, PyTorch, MXNet, Jax and NumPy. We also release four pure-Ivy libraries for mechanics, 3D vision, robotics, and differentiable environments. Through our evaluations, we show that Ivy can significantly reduce lines of code with a runtime overhead of less than 1% in most cases. We welcome developers to join the Ivy community by writing their own functions, layers and libraries in Ivy, maximizing their audience and helping to accelerate DL research through inter-framework codebases.' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 89d573f39917f..1655ef485e509 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 91ae3f63899a5..5ebb151775a5e 100644 --- a/README.md +++ b/README.md @@ -1,60 +1,55 @@ -> πŸš€ We are granting pilot access to **Ivy\'s Tracer and Transpiler** -> to some users, [join the waitlist](https://console.unify.ai/) if you -> want to test them out! - - +
+ +
- +
+ +
------------------------------------------------------------------------
- - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + +
------------------------------------------------------------------------- - -# Status +
-
- - +
+ + - - + + - - + + - + - - - - - + + @@ -62,9 +57,13 @@

------------------------------------------------------------------------- -# Unified AI +# Convert ML Models Between Frameworks + +Ivy is an open-source machine learning framework that enables you to: + +- Use your ML models and/or functions in any framework by converting any code from one framework to another using `ivy.transpile` +- Convert entire ML models and libraries between frameworks by generating identical source code in any frameworkusing `ivy.source_to_source` *(currently in private beta)*
@@ -91,103 +90,72 @@
------------------------------------------------------------------------- - -Ivy is an open-source machine learning framework that -enables you to: - -- πŸ”₯ **Autotune your model**: Automatically find the optimal framework, compiler infrastructure and hardware for your specific use case using `ivy.autotune`. -- πŸ”„ **Convert code into any framework**: Use and build on top of any model, library, or device by converting any code from one framework to another using `ivy.transpile`. -- βš’οΈ **Write framework-agnostic code**: Write your code once in ivy and then choose the most appropriate ML framework as the backend to leverage all the benefits and tools. - -[Join our growing community](https://discord.com/invite/sXyFF8tDtm) 🌍 to connect with people using Ivy. **Let\'s** [unify.ai](https://unify.ai) **together 🦾** +# Installing ivy ------------------------------------------------------------------------- - -# Getting started - -The best way to get familiar with Ivy is to go through the [Demos](https://unify.ai/docs/ivy/demos/examples_and_demos.html), a good starting point is [Learn The Basics](https://unify.ai/docs/ivy/demos/learn_the_basics.html). - -The most important notebooks are: - -- [How to convert your code between frameworks?](https://unify.ai/docs/ivy/demos/learn_the_basics/04_transpile_code.html) -- [How to write framework-agnostic code?](https://unify.ai/docs/ivy/demos/learn_the_basics/01_write_ivy_code.html) -- Accelerate your development (WIP) -- Autotune and optimize models (WIP) - ------------------------------------------------------------------------- - -## Installing ivy - -There are various ways to use Ivy, depending on your preferred -environment: - -### Installing using pip - -The easiest way to set up Ivy is to install it using pip with the -following command: +The easiest way to set up Ivy is to install it using **pip**: ``` bash pip install ivy ``` -or alternatively: - -``` bash -python3 -m pip install ivy -``` -
-Docker +Docker Images -If you prefer to use containers, we also have pre-built Docker images -with all the supported frameworks and some relevant packages already -installed, which you can pull from: +Given the challenges of maintaining installations of various frameworks in a single environment, +users who would want to test `ivy` with multiple frameworks at once can use our Docker images for a seamless experience. +You can pull the images from: ``` bash -docker pull unifyai/ivy:latest +docker pull transpileai/ivy:latest # CPU +docker pull transpileai/ivy:latest-gpu # GPU ``` -If you are working on a GPU device, you can pull from: - -``` bash -docker pull unifyai/ivy:latest-gpu -```
-From Source +From Source You can also install Ivy from source if you want to take advantage of the latest changes, but we can\'t ensure everything will work as -expected. :sweat_smile: +expected πŸ˜… ``` bash -git clone https://github.com/unifyai/ivy.git +git clone https://github.com/ivy-llc/ivy.git cd ivy pip install --user -e . ``` -or alternatively, for the last step: - -``` bash -python3 -m pip install --user -e . -``` - - If you want to set up testing and various frameworks it\'s probably best -to check out the [Contributing - Setting -Up](https://unify.ai/docs/ivy/overview/contributing/setting_up. html#setting-up) +to check out the [Setting Up](https://ivy.dev/docs/overview/contributing/setting_up.html) page, where OS-specific and IDE-specific instructions and video tutorials to do so are available!
------------------------------------------------------------------------- +
-## Using Ivy +# Getting started + +- [Website](https://ivy.dev) +- [Docs](https://ivy.dev/docs) +- [Demos](https://ivy.dev/demos) +- [Design](https://ivy.dev/docs/overview/design.html) +- [FAQ](https://ivy.dev/docs/overview/faq.html) -After installing Ivy, you can start using it straight away, for example: +[Ivy's transpiler](https://ivy.dev/docs/overview/design/ivy_as_a_transpiler.html) allows you convert code between different ML frameworks. Have a look at our [Quickstart](https://ivy.dev/docs/demos/quickstart.html) notebook to get a brief idea of the features! + +The most important notebooks are: + +- [How to convert your code between frameworks?](https://ivy.dev/docs/demos/learn_the_basics/04_transpile_code.html) +- [How to write framework-agnostic code?](https://ivy.dev/docs/demos/learn_the_basics/01_write_ivy_code.html) + +Beyond that, based on the frameworks you want to convert code between, there are a few more [examples](#using-ivy) further down this page πŸ‘‡ which contain a number of models and libraries transpiled between PyTorch, JAX, TensorFlow and NumPy. + +
+ +# Using ivy + +After installing ivy, you can start using it straight away, for example:
Transpiling any code from one framework to another @@ -202,8 +170,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) ``` @@ -233,25 +201,9 @@ After installing Ivy, you can start using it straight away, for example:
------------------------------------------------------------------------- - -# Documentation - -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). - - Explaining how we adhere to existing [standards](https://unify.ai/docs/ivy/overview/background/standardization.html#standardization) to make this happen. -- [Related Work](https://unify.ai/docs/ivy/overview/related_work.html): Which paints a picture of the role Ivy plays in the ML stack, comparing it to other existing solutions in terms of functionalities and abstraction level. -- [Design](https://unify.ai/docs/ivy/overview/design.html): A user-focused guide about the design decision behind the architecture and the main building blocks of Ivy. -- [Deep Dive](https://unify.ai/docs/ivy/overview/deep_dive.html): Which delves deeper into the implementation details of Ivy and is oriented towards potential contributors to the code base. - ------------------------------------------------------------------------- - -# Examples - -The [Examples page](https://unify.ai/demos/) features a wide range of +\ +The [Examples page](https://ivy.dev/docs/demos/) features a wide range of demos and tutorials showcasing the functionalities of Ivy along with multiple use cases, but feel free to check out some shorter framework-specific examples here ⬇️ @@ -277,7 +229,7 @@ eff_encoder = tf.keras.applications.efficientnet_v2.EfficientNetV2B0( # Transpile it into a torch.nn.Module with the corresponding parameters noise = tf.random.normal(shape=(1, 224, 224, 3)) -torch_eff_encoder = ivy.transpile(eff_encoder, to="torch", args=(noise,)) +torch_eff_encoder = ivy.transpile(eff_encoder, source="tensorflow", to="torch", args=(noise,)) # Build a classifier using the transpiled encoder class Classifier(torch.nn.Module): @@ -305,14 +257,15 @@ import jax import torch # Get a pretrained haiku model -# https://unify.ai/demos/scripts/deepmind_perceiver_io.py +# https://github.com/unifyai/demos/blob/15c235f/scripts/deepmind_perceiver_io.py from deepmind_perceiver_io import key, perceiver_backbone # Transpile it into a torch.nn.Module with the corresponding parameters dummy_input = jax.random.uniform(key, shape=(1, 3, 224, 224)) params = perceiver_backbone.init(rng=key, images=dummy_input) +ivy.set_backend("jax") backbone = ivy.transpile( - perceiver_backbone, to="torch", params_v=params, kwargs={"images": dummy_input} + perceiver_backbone, source="jax", to="torch", params_v=params, kwargs={"images": dummy_input} ) # Build a classifier using the transpiled backbone @@ -532,7 +485,7 @@ import jax import tensorflow as tf # Get a pretrained haiku model -# https://unify.ai/demos/scripts/deepmind_perceiver_io.py +# https://ivy.dev/demos/scripts/deepmind_perceiver_io.py from deepmind_perceiver_io import key, perceiver_backbone # Transpile it into a tf.keras.Model with the corresponding parameters @@ -738,7 +691,7 @@ mlp_encoder = timm.create_model("mixer_b16_224", pretrained=True, num_classes=0) # Transpile it into a hk.Module with the corresponding parameters noise = torch.randn(1, 3, 224, 224) -mlp_encoder = ivy.transpile(mlp_encoder, to="jax", args=(noise,)) +mlp_encoder = ivy.transpile(mlp_encoder, source="torch", to="haiku", args=(noise,)) # Build a classifier using the transpiled encoder class Classifier(hk.Module): @@ -774,6 +727,7 @@ import ivy import jax import haiku as hk import tensorflow as tf +jax.config.update("jax_enable_x64", True) # Get a pretrained keras model eff_encoder = tf.keras.applications.efficientnet_v2.EfficientNetV2B0( @@ -782,7 +736,7 @@ eff_encoder = tf.keras.applications.efficientnet_v2.EfficientNetV2B0( # Transpile it into a hk.Module with the corresponding parameters noise = tf.random.normal(shape=(1, 224, 224, 3)) -hk_eff_encoder = ivy.transpile(eff_encoder, to="jax", args=(noise,)) +hk_eff_encoder = ivy.transpile(eff_encoder, source="tensorflow", to="haiku", args=(noise,)) # Build a classifier using the transpiled encoder class Classifier(hk.Module): @@ -825,6 +779,7 @@ import kornia import requests import jax.numpy as jnp from PIL import Image +jax.config.update("jax_enable_x64", True) # transpile kornia from torch to jax jax_kornia = ivy.transpile(kornia, source="torch", to="jax") @@ -1123,230 +1078,36 @@ out = np_loss(p, t) -
- -I'm using Ivy  - -Or you can use Ivy as a framework, breaking yourself (and your code) -free from deciding which community to support, allowing anyone to run -your code in their framework of choice! - -``` python -import ivy - -# A simple image classification model -class IvyNet(ivy.Module): - def __init__( - self, - h_w=(32, 32), - input_channels=3, - output_channels=512, - num_classes=2, - data_format="NCHW", - device="cpu", - ): - self.h_w = h_w - self.input_channels = input_channels - self.output_channels = output_channels - self.num_classes = num_classes - self.data_format = data_format - self.device = device - super().__init__() - - def _build(self, *args, **kwargs): - self.extractor = ivy.Sequential( - ivy.Conv2D(self.input_channels, 6, [5, 5], 1, "SAME", data_format=self.data_format), - ivy.GELU(), - ivy.Conv2D(6, 16, [5, 5], 1, "SAME", data_format=self.data_format), - ivy.GELU(), - ivy.Conv2D(16, self.output_channels, [5, 5], 1, "SAME", data_format=self.data_format), - ivy.GELU(), - ) - - self.classifier = ivy.Sequential( - # Since the padding is "SAME", this would be image_height x image_width x output_channels - ivy.Linear(self.h_w[0] * self.h_w[1] * self.output_channels, 512), - ivy.GELU(), - ivy.Linear(512, self.num_classes), - ) - - def _forward(self, x): - x = self.extractor(x) - # flatten all dims except batch dim - x = ivy.flatten(x, start_dim=1, end_dim=-1) - logits = self.classifier(x) - probs = ivy.softmax(logits) - return logits, probs -``` - -After building your model in Ivy, you can set your favourite framework -as the backend to use its operations under the hood! - -``` python -ivy.set_backend("torch") -model = IvyNet() -x = torch.randn(1, 3, 32, 32) -logits, probs = model(x) -``` - -``` python -ivy.set_backend("tensorflow") -model = IvyNet() -x = tf.random.uniform(shape=(1, 3, 32, 32)) -logits, probs = model(x) -``` - -``` python -ivy.set_backend("jax") -model = IvyNet() -x = jax.random.uniform(key, shape=(1, 3, 32, 32)) -logits, probs = model(x) -``` - -``` python -ivy.set_backend("numpy") -model = IvyNet() -x = np.random.uniform(size=(1, 3, 32, 32)) -logits, probs = model(x) -``` -Last but not least, we can also build the training pipeline in pure ivy -⬇️ +\ +For a more comprehensive overview, head over to the [Demos](https://ivy.dev/docs/demos/index.html) section with more on the [basics](https://ivy.dev/docs/demos/learn_the_basics.html), a few [guides](https://ivy.dev/docs/demos/guides.html) and a wide-ranging set of [examples](https://ivy.dev/docs/demos/examples_and_demos.html) that demonstrate the transpilation of various popular models. We continue to expand on that list, let us know what demos you'd like us to add next 🎯 -
-Let's define some helper functions first +
-``` python -# helper function for loading the dataset in batches -def generate_batches(images, classes, dataset_size, batch_size=32): - targets = {k: v for v, k in enumerate(np.unique(classes))} - y_train = [targets[classes[i]] for i in range(len(classes))] - if batch_size > dataset_size: - raise ivy.utils.exceptions.IvyError("Use a smaller batch size") - for idx in range(0, dataset_size, batch_size): - yield ivy.stack(images[idx : min(idx + batch_size, dataset_size)]), ivy.array( - y_train[idx : min(idx + batch_size, dataset_size)] - ) - - -# helper function to get the number of current predictions -def num_correct(preds, labels): - return (preds.argmax() == labels).sum().to_numpy().item() - - -# define a loss function -def loss_fn(params): - v, model, x, y = params - y_pred, probs = model(x) - return ivy.cross_entropy(y, probs), probs -``` +# How ivy works? -
+Let's take a look at how Ivy works as a transpiler in more detail to get an idea of why and where to use it. +
-And train this model! +When is Ivy's transpiler useful? -``` python -# train the model on gpu if it's available -device = "cuda:0" if ivy.gpu_is_available() else "cpu" - -# training hyperparams -optimizer= ivy.Adam(1e-4) -batch_size = 64 -num_epochs = 20 -num_classes = 10 - -model = IvyNet( - h_w=(28, 28), - input_channels=1, - output_channels=120, - num_classes=num_classes, - device=device, -) -model_name = type(model).__name__.lower() - - -# training loop -def train(images, classes, epochs, model, device, num_classes=10, batch_size=32): - # training metrics - epoch_loss = 0.0 - running_loss = 0.0 - fields = ["epoch", "epoch_loss", "training_accuracy"] - metrics = [] - dataset_size = len(images) - - for epoch in range(epochs): - train_loss, train_correct = 0, 0 - train_loop = tqdm( - generate_batches(images, classes, len(images), batch_size=batch_size), - total=dataset_size // batch_size, - position=0, - leave=True, - ) - - for xbatch, ybatch in train_loop: - if device != "cpu": - xbatch, ybatch = xbatch.to_device("gpu:0"), ybatch.to_device("gpu:0") - - # Since the cross entropy function expects the target classes to be in one-hot encoded format - ybatch_encoded = ivy.one_hot(ybatch, num_classes) - - # update model params - loss_probs, grads = ivy.execute_with_gradients( - loss_fn, - (model.v, model, xbatch, ybatch_encoded), - ) - - model.v = optimizer.step(model.v, grads["0"]) - - batch_loss = ivy.to_numpy(loss_probs[0]).mean().item() # batch mean loss - epoch_loss += batch_loss * xbatch.shape[0] - train_correct += num_correct(loss_probs[1], ybatch) - - train_loop.set_description(f"Epoch [{epoch + 1:2d}/{epochs}]") - train_loop.set_postfix( - running_loss=batch_loss, - accuracy_percentage=(train_correct / dataset_size) * 100, - ) - - epoch_loss = epoch_loss / dataset_size - training_accuracy = train_correct / dataset_size - - metrics.append([epoch, epoch_loss, training_accuracy]) - - train_loop.write( - f"\nAverage training loss: {epoch_loss:.6f}, Train Correct: {train_correct}", - end="\n", - ) - - # write metrics for plotting - with open(f"/{model_name}_train_summary.csv", "w") as f: - f = csv.writer(f) - f.writerow(fields) - f.writerows(metrics) - - -# assuming the dataset(images and classes) are already prepared in a folder -train(images, classes, num_epochs, model, device, num_classes = num_classes, batch_size = batch_size) -``` - -
+If you want to use building blocks published in other frameworks (neural +networks, layers, array computing libraries, training pipelines\...), +you want to integrate code developed in various frameworks, or maybe +straight up migrate code from one framework to another or even between versions of the same framework, the transpiler is +definitely the tool for the job! You can use the converted code just +as if it was code originally developed in that framework, applying +framework-specific optimizations or tools, instantly exposing your +project to all of the unique perks of a different framework.
+ ------------------------------------------------------------------------- - -# 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 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 - +\ Ivy\'s transpiler allows you to use code from any other framework (or from any other version of the same framework!) in your own code, by just adding one line of code. Under the hood, Ivy traces a computational -graph and leverages the frontends and backends to link one framework to -another. +graph and leverages the frontends and backends to link one version of one framework to another version of another framework. This way, Ivy makes all ML-related projects available for you, independently of the framework you want to use to research, develop, or @@ -1354,13 +1115,13 @@ deploy systems. Feel free to head over to the docs for the full API reference, but the functions you\'d most likely want to use are: ``` python -# Traces an efficient fully-functional graph from a function, removing all wrapping and redundant code +# Traces an efficient fully-functional graph from a function, removing all wrapping and redundant code. See usage in the documentation ivy.trace_graph() -# Converts framework-specific code to a different framework +# Converts framework-specific code to a target framework of choice. See usage in the documentation ivy.transpile() -# Converts framework-specific code to Ivy +# Converts framework-specific code to Ivy's framework-agnostic API. See usage in the documentation ivy.unify() ``` @@ -1402,208 +1163,54 @@ ret = lazy_graph(x1) If you want to learn more, you can find more information in the [Ivy as a transpiler section of the -docs!](https://unify.ai/docs/ivy/overview/design/ivy_as_a_transpiler.html) - -## When should I use Ivy as a transpiler? +docs!](https://ivy.dev/docs/overview/design/ivy_as_a_transpiler.html) -If you want to use building blocks published in other frameworks (neural -networks, layers, array computing libraries, training pipelines\...), -you want to integrate code developed in various frameworks, or maybe -straight up move code from one framework to another, the transpiler is -definitely the tool πŸ”§ for the job! As the output of transpilation is -native code in the target framework, you can use the converted code just -as if it was code originally developed in that framework, applying -framework-specific optimizations or tools, instantly exposing your -project to all of the unique perks of a different framework. -
+
-
-Ivy as a framework - -The Ivy framework is built on top of various essential components, -mainly the [Backend -Handler](https://unify.ai/docs/ivy/overview/design/building_blocks.html#backend-handler), -which manages what framework is being used behind the scenes and the -[Backend Functional -APIs](https://unify.ai/docs/ivy/overview/design/building_blocks.html#backend-functional-apis), -which provide framework-specific implementations of the Ivy functions. -Likewise, classes such as `ivy.Container` or `ivy.Array` are also -available, facilitating the use of structured data and array-like -objects (learn more about them -[here!](https://unify.ai/docs/ivy/overview/design/ivy_as_a_framework.html)). - -All of the functionalities in Ivy are exposed through the -`Ivy functional API` and the `Ivy stateful API`. All functions in the -[Functional -API](https://unify.ai/docs/ivy/overview/design/building_blocks.html#ivy-functional-api) -are **Framework Agnostic Functions**, which means that we can use them -like this: - -``` python -import ivy -import jax.numpy as jnp -import tensorflow as tf -import numpy as np -import torch - -def mse_loss(y, target): - return ivy.mean((y - target)**2) - -jax_mse = mse_loss(jnp.ones((5,)), jnp.ones((5,))) -tf_mse = mse_loss(tf.ones((5,)), tf.ones((5,))) -np_mse = mse_loss(np.ones((5,)), np.ones((5,))) -torch_mse = mse_loss(torch.ones((5,)), torch.ones((5,))) -``` - -In the example above we show how Ivy\'s functions are compatible with -tensors from different frameworks. This is the same for ALL Ivy -functions. They can accept tensors from any framework and return the -correct result. - -The [Ivy Stateful -API](https://unify.ai/docs/ivy/overview/design/ivy_as_a_framework/ivy_stateful_api.html), -on the other hand, allows you to define trainable modules and layers, -which you can use alone or as a part of any other framework code! - -``` python -import ivy - - -class Regressor(ivy.Module): - def __init__(self, input_dim, output_dim): - self.input_dim = input_dim - self.output_dim = output_dim - super().__init__() - - def _build(self, *args, **kwargs): - self.linear0 = ivy.Linear(self.input_dim, 128) - self.linear1 = ivy.Linear(128, self.output_dim) - - def _forward(self, x): - x = self.linear0(x) - x = ivy.functional.relu(x) - x = self.linear1(x) - return x -``` - -If we put it all together, we\'ll have something like this. This example -uses PyTorch as the backend, but this can easily be changed to your -favorite frameworks, such as TensorFlow, or JAX. - -``` python -import ivy - - -class Regressor(ivy.Module): - def __init__(self, input_dim, output_dim): - self.input_dim = input_dim - self.output_dim = output_dim - super().__init__() - - def _build(self, *args, **kwargs): - self.linear0 = ivy.Linear(self.input_dim, 128) - self.linear1 = ivy.Linear(128, self.output_dim) - - def _forward(self, x): - x = self.linear0(x) - x = ivy.functional.relu(x) - x = self.linear1(x) - return x - -ivy.set_backend('torch') # set backend to PyTorch (or any other backend!) - -model = Regressor(input_dim=1, output_dim=1) -optimizer = ivy.Adam(0.3) - -n_training_examples = 2000 -noise = ivy.random.random_normal(shape=(n_training_examples, 1), mean=0, std=0.1) -x = ivy.linspace(-6, 3, n_training_examples).reshape((n_training_examples, 1)) -y = 0.2 * x ** 2 + 0.5 * x + 0.1 + noise - - -def loss_fn(v, x, target): - pred = model(x, v=v) - return ivy.mean((pred - target) ** 2) - -for epoch in range(40): - # forward pass - pred = model(x) - - # compute loss and gradients - loss, grads = ivy.execute_with_gradients(lambda params: loss_fn(*params), (model.v, x, y)) - - # update parameters - model.v = optimizer.step(model.v, grads) - - # print current loss - print(f'Epoch: {epoch + 1:2d} --- Loss: {ivy.to_numpy(loss).item():.5f}') - -print('Finished training!') -``` - -The model\'s output can be visualized as follows: - -
- -
- -As always, you can find more information about [Ivy as a framework in -the -docs!](https://unify.ai/docs/ivy/overview/design/ivy_as_a_framework.html) - -

When should I use Ivy as a framework?

+# Documentation -As Ivy supports multiple backends, writing code in Ivy breaks you free -from framework limitations. If you want to publish highly flexible code -for everyone to use, independently of the framework they are using, or -you plan to develop ML-related tools and want them to be interoperable -with not only the already existing frameworks, but also with future -frameworks, then Ivy is for you! +You can find Ivy's documentation on the [Docs page](https://ivy.dev/docs/), which includes: +- [Motivation](https://ivy.dev/docs/overview/motivation.html): This contextualizes the problem Ivy is trying to solve by going over + - The current [ML Explosion](https://ivy.dev/docs/overview/motivation/ml_explosion.html#ml-explosion). + - Explaining why it is important [to solve this problem](https://ivy.dev/docs/overview/motivation/why_unify.html#why-unify). + - Explaining how we adhere to existing [standards](https://ivy.dev/docs/overview/motivation/standardization.html#standardization) to make this happen. +- [Related Work](https://ivy.dev/docs/overview/related_work.html): Which paints a picture of the role Ivy plays in the ML stack, comparing it to other existing solutions in terms of functionalities and abstraction level. +- [Design](https://ivy.dev/docs/overview/design.html): A user-focused guide about the design decision behind the architecture and the main building blocks of Ivy. +- [Deep Dive](https://ivy.dev/docs/overview/deep_dive.html): Which delves deeper into the implementation details of Ivy and is oriented towards potential contributors to the code base. -
- ------------------------------------------------------------------------- +
# Contributing We believe that everyone can contribute and make a difference. Whether -it\'s writing code πŸ’», fixing bugs πŸ›, or simply sharing feedback πŸ’¬, +it\'s writing code, fixing bugs, or simply sharing feedback, your contributions are definitely welcome and appreciated πŸ™Œ -Check out all of our open tasks, and find out more info in our -[Contributing -guide](https://unify.ai/docs/ivy/overview/contributing.html) in the -docs! - -Join our amazing community as a code contributor, and help accelerate -our journey to unify all ML frameworks! +Check out all of our [Open Tasks](https://ivy.dev/docs/overview/contributing/open_tasks.html), +and find out more info in our [Contributing guide](https://ivy.dev/docs/overview/contributing.html) +in the docs! Or to immediately dive into a useful task, look for any failing tests on our [Test Dashboard](https://github.com/ivy-llc/ivy-tests-dashboard/blob/main/DASHBOARD.md)! - - + + ------------------------------------------------------------------------- +
# Community -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 on -our [Discord](https://discord.gg/sXyFF8tDtm) πŸ‘Ύ server, which is the +Join our growing community on a mission to make conversions between frameworks simple and accessible to all! +Whether you are a seasoned developer or just starting out, you\'ll find a place here! Join the Ivy community on +our [Discord](https://discord.gg/mMnS8Egy) πŸ‘Ύ server, which is the perfect place to ask questions, share ideas, and get help from both -fellow developers and the Ivy Team directly! +fellow developers and the Ivy Team directly. -Also! Feel free to follow us on -[Twitter](https://twitter.com/letsunifyai) 🐦 as well, we use it to -share updates, sneak peeks, and all sorts of relevant news, certainly a -great way to stay in the loop πŸ˜„ + See you there! -Can\'t wait to see you there! ------------------------------------------------------------------------- +
# Citation 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/badges/badge_01-00.png b/badges/badge_01-00.png new file mode 100644 index 0000000000000..510aac570e088 Binary files /dev/null and b/badges/badge_01-00.png differ diff --git a/badges/badge_01-01.png b/badges/badge_01-01.png new file mode 100644 index 0000000000000..215259bf62a35 Binary files /dev/null and b/badges/badge_01-01.png differ diff --git a/badges/badge_01-02.png b/badges/badge_01-02.png new file mode 100644 index 0000000000000..91ee4816e2cd3 Binary files /dev/null and b/badges/badge_01-02.png differ diff --git a/badges/badge_01-03.png b/badges/badge_01-03.png new file mode 100644 index 0000000000000..0738e81cafe42 Binary files /dev/null and b/badges/badge_01-03.png differ diff --git a/badges/badge_01-04.png b/badges/badge_01-04.png new file mode 100644 index 0000000000000..000014f6304dd Binary files /dev/null and b/badges/badge_01-04.png differ diff --git a/badges/badge_02-00.png b/badges/badge_02-00.png new file mode 100644 index 0000000000000..7def394f4a7e6 Binary files /dev/null and b/badges/badge_02-00.png differ diff --git a/badges/badge_02-01.png b/badges/badge_02-01.png new file mode 100644 index 0000000000000..79eba89c369a0 Binary files /dev/null and b/badges/badge_02-01.png differ diff --git a/badges/badge_02-02.png b/badges/badge_02-02.png new file mode 100644 index 0000000000000..623667665d7fa Binary files /dev/null and b/badges/badge_02-02.png differ diff --git a/badges/badge_02-03.png b/badges/badge_02-03.png new file mode 100644 index 0000000000000..4f6748d6f05e8 Binary files /dev/null and b/badges/badge_02-03.png differ diff --git a/badges/badge_02-04.png b/badges/badge_02-04.png new file mode 100644 index 0000000000000..b0abc6880e3c9 Binary files /dev/null and b/badges/badge_02-04.png differ diff --git a/badges/badge_03-00.png b/badges/badge_03-00.png new file mode 100644 index 0000000000000..baa3be951514c Binary files /dev/null and b/badges/badge_03-00.png differ diff --git a/badges/badge_03-01.png b/badges/badge_03-01.png new file mode 100644 index 0000000000000..736b322ea6654 Binary files /dev/null and b/badges/badge_03-01.png differ diff --git a/badges/badge_03-02.png b/badges/badge_03-02.png new file mode 100644 index 0000000000000..c4a66dfc4ce69 Binary files /dev/null and b/badges/badge_03-02.png differ diff --git a/badges/badge_03-03.png b/badges/badge_03-03.png new file mode 100644 index 0000000000000..13d327fcaa5df Binary files /dev/null and b/badges/badge_03-03.png differ diff --git a/badges/badge_03-04.png b/badges/badge_03-04.png new file mode 100644 index 0000000000000..b90edfbe5c0a7 Binary files /dev/null and b/badges/badge_03-04.png differ diff --git a/badges/badge_04-00.png b/badges/badge_04-00.png new file mode 100644 index 0000000000000..6e1e908ca00ad Binary files /dev/null and b/badges/badge_04-00.png differ diff --git a/badges/badge_04-01.png b/badges/badge_04-01.png new file mode 100644 index 0000000000000..779c6d5c5903c Binary files /dev/null and b/badges/badge_04-01.png differ diff --git a/badges/badge_04-02.png b/badges/badge_04-02.png new file mode 100644 index 0000000000000..5f00f0979da6d Binary files /dev/null and b/badges/badge_04-02.png differ diff --git a/badges/badge_04-03.png b/badges/badge_04-03.png new file mode 100644 index 0000000000000..185b14db61888 Binary files /dev/null and b/badges/badge_04-03.png differ diff --git a/badges/badge_04-04.png b/badges/badge_04-04.png new file mode 100644 index 0000000000000..c2de61e386b27 Binary files /dev/null and b/badges/badge_04-04.png differ diff --git a/badges/badge_05-00.png b/badges/badge_05-00.png new file mode 100644 index 0000000000000..5ca5c1c4c41aa Binary files /dev/null and b/badges/badge_05-00.png differ diff --git a/badges/badge_05-01.png b/badges/badge_05-01.png new file mode 100644 index 0000000000000..08f51225c9f60 Binary files /dev/null and b/badges/badge_05-01.png differ diff --git a/badges/badge_05-02.png b/badges/badge_05-02.png new file mode 100644 index 0000000000000..5ea36dbb9644c Binary files /dev/null and b/badges/badge_05-02.png differ diff --git a/badges/badge_05-03.png b/badges/badge_05-03.png new file mode 100644 index 0000000000000..559ff5b4c70e5 Binary files /dev/null and b/badges/badge_05-03.png differ diff --git a/badges/badge_05-04.png b/badges/badge_05-04.png new file mode 100644 index 0000000000000..3d22c2ba8b6c7 Binary files /dev/null and b/badges/badge_05-04.png differ diff --git a/badges/badge_06-00.png b/badges/badge_06-00.png new file mode 100644 index 0000000000000..afcf15142bef7 Binary files /dev/null and b/badges/badge_06-00.png differ diff --git a/badges/badge_06-01.png b/badges/badge_06-01.png new file mode 100644 index 0000000000000..03696a1e1567a Binary files /dev/null and b/badges/badge_06-01.png differ diff --git a/badges/badge_06-02.png b/badges/badge_06-02.png new file mode 100644 index 0000000000000..53460d28f2603 Binary files /dev/null and b/badges/badge_06-02.png differ diff --git a/badges/badge_06-03.png b/badges/badge_06-03.png new file mode 100644 index 0000000000000..1c366f4e0fdc7 Binary files /dev/null and b/badges/badge_06-03.png differ diff --git a/badges/badge_06-04.png b/badges/badge_06-04.png new file mode 100644 index 0000000000000..6f237981a0b54 Binary files /dev/null and b/badges/badge_06-04.png differ diff --git a/binaries.json b/binaries.json index f77586c81524f..c9eb6cde72066 100644 --- a/binaries.json +++ b/binaries.json @@ -1,95 +1,142 @@ { "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", + "ICC", + "ICD", + "ICI", + "ICL", + "ICM", + "ICV", + "ICX", + "ID", + "IDC", + "IDD", + "IDI", + "IDL", + "IDM", + "IDV", + "IDX", + "II", + "IIC", + "IID", + "III", + "IIL", + "IIM", + "IIV", + "IIX", + "IL", + "ILC", + "ILD", + "ILI", + "ILL", + "ILM", + "ILV", + "ILX", + "IM", + "IMC", + "IMD", + "IMI", + "IML", + "IMM", + "IMV", + "IMX", + "IV", + "IVC", + "IVD", + "IVI", + "IVL", + "IVM", + "IVV", + "IVX", + "IX", + "IXC", + "IXD", + "IXI", + "IXL", + "IXM", + "IXV", + "IXX", + "L", + "LC", + "LD", + "LI", + "LL", + "LM", + "LV", + "LX", + "M", + "MC", + "MD", + "MI", + "ML", + "MM", + "MV", + "MX", + "V", + "VC", + "VD", + "VI", + "VIC", + "VID", + "VII", + "VIL", + "VIM", + "VIV", + "VIX", + "VL", + "VLC", + "VLI", + "VLL", + "VLV", + "VLX", + "VM", + "VV", + "VVC", + "VVD", + "VVI", + "VVL", + "VVM", + "VVV", + "VVX", + "VX", + "VXC", + "VXD", + "VXI", + "VXL", + "VXM", + "VXV", + "VXX", + "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/Dockerfile b/docker/Dockerfile index 173982af80053..f74ba7704f606 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -15,7 +15,7 @@ RUN apt clean && \ apt-get install -y wget \ git -y && \ wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh && \ - /bin/bash ~/miniconda.sh -b -p /opt/miniconda + /bin/bash ~/miniconda.sh -b -p /opt/miniconda ENV PATH=$CONDA_DIR/bin:$PATH @@ -39,7 +39,7 @@ RUN apt-get update && \ # Install Ivy Upstream -RUN git clone --progress --recurse-submodules https://github.com/unifyai/ivy --depth 1 && \ +RUN git clone --progress --recurse-submodules https://github.com/ivy-llc/ivy --depth 1 && \ cd ivy && \ cd ivy_tests/array_api_testing/test_array_api && \ pip3 install --no-cache-dir -r requirements.txt @@ -48,13 +48,6 @@ RUN git clone --progress --recurse-submodules https://github.com/unifyai/ivy --d # Install local optional COPY requirements/optional.txt . COPY requirements/requirements.txt . -#setting torch path early on because torch-scatter needs it -ENV PYTHONPATH "/opt/fw/torch:/opt/miniconda/envs/multienv/bin" - -#torch and torch scatter separate installation because they cause issues -RUN pip3 install --no-cache-dir torch --target '/opt/fw/torch' --extra-index-url https://download.pytorch.org/whl/cpu -RUN export ver=$(pip show torch --path '/opt/fw/torch' | grep Version | cut -d ' ' -f2) && \ - pip3 install --target '/opt/fw/torch' --no-cache-dir --upgrade torch-scatter -f https://data.pyg.org/whl/torch-$ver.html # requirement mappings directs which dependency to be installed and where COPY /docker/requirement_mappings.json . diff --git a/docker/DockerfileAppleSilicon b/docker/DockerfileAppleSilicon index b0d258ad19646..1e8408fd38059 100644 --- a/docker/DockerfileAppleSilicon +++ b/docker/DockerfileAppleSilicon @@ -187,7 +187,7 @@ RUN apt-get update && \ pip3 install setuptools==58.5.3 # Install Ivy Upstream -RUN git clone --progress --recurse-submodules https://github.com/unifyai/ivy --depth 1 && \ +RUN git clone --progress --recurse-submodules https://github.com/ivy-llc/ivy --depth 1 && \ cd ivy && \ cd ivy_tests/array_api_testing/test_array_api && \ pip3 install --no-cache-dir -r requirements.txt @@ -197,14 +197,6 @@ COPY requirements/optional_apple_silicon_1.txt . COPY requirements/optional_apple_silicon_2.txt . COPY requirements/requirements.txt . -# setting torch path early on because torch-scatter needs it -ENV PYTHONPATH "/opt/fw/torch" - -#torch and torch scatter separate installation because they cause issues -RUN pip3 install --no-cache-dir torch --target '/opt/fw/torch' --extra-index-url https://download.pytorch.org/whl/cpu -RUN export ver=$(pip show torch --path '/opt/fw/torch' | grep Version | cut -d ' ' -f2) && \ - pip3 install --target '/opt/fw/torch' --no-cache-dir --upgrade torch-scatter -f https://data.pyg.org/whl/torch-$ver.html - # requirement mappings directs which dependency to be installed and where COPY /docker/requirement_mappings_apple_silicon.json . SHELL ["/bin/bash", "-c"] diff --git a/docker/DockerfileApplied b/docker/DockerfileApplied index 290c251054668..c1f484342bca2 100644 --- a/docker/DockerfileApplied +++ b/docker/DockerfileApplied @@ -2,7 +2,7 @@ FROM ubuntu:20.04 WORKDIR /ivy ARG CLI -FROM unifyai/ivy:latest as base +FROM transpileai/ivy:latest as base COPY requirements/optional_applied.txt . RUN pip3 install --no-cache-dir -r optional_applied.txt diff --git a/docker/DockerfileGPU b/docker/DockerfileGPU index 7cef64508c005..06a98aaca6d9e 100644 --- a/docker/DockerfileGPU +++ b/docker/DockerfileGPU @@ -35,7 +35,7 @@ RUN apt clean && \ apt-get install -y jq && \ apt-get install git -y && \ wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh && \ - /bin/bash ~/miniconda.sh -b -p /opt/miniconda + /bin/bash ~/miniconda.sh -b -p /opt/miniconda # create conda environment @@ -58,7 +58,7 @@ RUN apt-get update && \ # install Ivy Upstream -RUN git clone --progress --recurse-submodules https://github.com/unifyai/ivy --depth 1 && \ +RUN git clone --progress --recurse-submodules https://github.com/ivy-llc/ivy --depth 1 && \ cd ivy && \ cd ivy_tests/array_api_testing/test_array_api && \ pip3 install --no-cache-dir -r requirements.txt diff --git a/docker/DockerfileMultiversion b/docker/DockerfileMultiversion index 2a62a25c726aa..80710050e4e4b 100644 --- a/docker/DockerfileMultiversion +++ b/docker/DockerfileMultiversion @@ -11,7 +11,7 @@ RUN apt clean && \ apt-get update && \ apt-get install -y wget && \ wget --quiet https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda.sh && \ - /bin/bash ~/miniconda.sh -b -p /opt/miniconda + /bin/bash ~/miniconda.sh -b -p /opt/miniconda ENV PATH=$CONDA_DIR/bin:$PATH RUN conda create --name multienv python==$pycon @@ -32,7 +32,7 @@ RUN apt-get update && \ # Install Ivy Upstream -RUN git clone --progress --recurse-submodules https://github.com/unifyai/ivy --depth 1 && \ +RUN git clone --progress --recurse-submodules https://github.com/ivy-llc/ivy --depth 1 && \ cd ivy && \ cd ivy_tests/array_api_testing/test_array_api && \ pip3 install --no-cache-dir -r requirements.txt diff --git a/docker/build_applied_dockerfile.sh b/docker/build_applied_dockerfile.sh index c6098626c8883..3fda50613781c 100644 --- a/docker/build_applied_dockerfile.sh +++ b/docker/build_applied_dockerfile.sh @@ -1,3 +1,3 @@ #!/bin/bash -docker build -t unifyai/ivy:latest --no-cache -f DockerfileApplied .. +docker build -t transpileai/ivy:latest --no-cache -f DockerfileApplied .. diff --git a/docker/build_gpu_dockerfile.sh b/docker/build_gpu_dockerfile.sh index ec946c8b97e89..3d49e4c89192c 100644 --- a/docker/build_gpu_dockerfile.sh +++ b/docker/build_gpu_dockerfile.sh @@ -1 +1 @@ -docker build --progress=plain --no-cache -t unifyai/ivy:latest-gpu -f DockerfileGPU .. +docker build --progress=plain --no-cache -t transpileai/ivy:latest-gpu -f DockerfileGPU .. diff --git a/docker/build_multiversiondockerfile.sh b/docker/build_multiversiondockerfile.sh index 1bf3628ec606d..67cc99ba42131 100644 --- a/docker/build_multiversiondockerfile.sh +++ b/docker/build_multiversiondockerfile.sh @@ -1,3 +1,3 @@ #!/bin/bash -docker build --progress=plain -t unifyai/multiversion:base -f MultiversionDockerFile .. +docker build --progress=plain -t transpileai/multiversion:base -f MultiversionDockerFile .. diff --git a/docker/gpu_framework_directory.py b/docker/gpu_framework_directory.py index 21ed1e2fcf989..bd219a972af33 100644 --- a/docker/gpu_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,12 +40,19 @@ 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": subprocess.run( - f"yes |pip install --upgrade --target {path} 'jax[cuda11_pip]' -f" + f"yes |pip install --upgrade --target {path} 'jax[cuda12_pip]' -f" " https://storage.googleapis.com/jax-releases/jax_cuda_releases.html " " --no-cache-dir", shell=True, @@ -53,15 +60,14 @@ 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}", + f"yes |pip install tensorflow[and-cuda]==2.15.1 --target {path}", shell=True, ) else: diff --git a/docker/rebuild_all_dockerfiles.sh b/docker/rebuild_all_dockerfiles.sh index 386faff74fae5..19bbce0fba88f 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/ivy:latest-gpu --no-cache -f DockerfileGPU .. +docker build -t transpileai/ivy:latest --no-cache -f Dockerfile .. +docker build -t transpileai/ivy:latest-gpu --no-cache -f DockerfileGPU .. diff --git a/docker/requirement_mappings.json b/docker/requirement_mappings.json index 61b4ad87e17a5..09d17a4874299 100644 --- a/docker/requirement_mappings.json +++ b/docker/requirement_mappings.json @@ -1,5 +1,5 @@ { - "tensorflow": ["tensorflow-cpu", "tensorflow-probability"], + "tensorflow": ["tensorflow-cpu==2.15.1", "tensorflow-probability"], "jax": ["ml-dtypes","jax[cpu]","dm-haiku", "flax", "jaxlib"], "numpy": ["numpy"], "paddle": ["paddlepaddle"], 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 a851f62b1ce3f..55c4a5cb59287 100644 --- a/docker/requirement_mappings_gpu.json +++ b/docker/requirement_mappings_gpu.json @@ -1,7 +1,18 @@ { - "jax": ["dm-haiku", "flax"], - "numpy": ["numpy"], - "mxnet": ["mxnet"], - "torch": ["torch-scatter", "torchvision"], - "tensorflow": ["tensorflow-probability"] + "jax": [ + "dm-haiku", + "flax" + ], + "numpy": [ + "numpy" + ], + "mxnet": [ + "mxnet" + ], + "torch": [ + "torchvision" + ], + "tensorflow": [ + "tensorflow-probability" + ] } diff --git a/docker/requirement_mappings_multiversion.json b/docker/requirement_mappings_multiversion.json index 7eaa8101d5730..2a818d0e96461 100644 --- a/docker/requirement_mappings_multiversion.json +++ b/docker/requirement_mappings_multiversion.json @@ -1,41 +1,40 @@ { - "tensorflow": [ - { - "tensorflow-probability": { - "2.13.0": "0.21.0", - "2.12.0": "0.20.0", - "2.11.0": "0.19.0" - } - } - ], - "jax": [ - "dm-haiku", - "flax", - { - "jaxlib": { - "0.4.17": "0.4.17", - "0.4.14": "0.4.14", - "0.4.10": "0.4.10", - "0.4.8": "0.4.7" - } - }, - { - "ml_dtypes": { - "0.4.10": "0.2.0" - } - } - ], - "numpy": [ - "numpy" - ], - "paddlepaddle": [ - "paddlepaddle" - ], - "mxnet": [ - "mxnet" - ], - "torch": [ - "torch-scatter", - "torchvision" - ] + "tensorflow": [ + { + "tensorflow-probability": { + "2.13.0": "0.21.0", + "2.12.0": "0.20.0", + "2.11.0": "0.19.0" + } + } + ], + "jax": [ + "dm-haiku", + "flax", + { + "jaxlib": { + "0.4.17": "0.4.17", + "0.4.14": "0.4.14", + "0.4.10": "0.4.10", + "0.4.8": "0.4.7" + } + }, + { + "ml_dtypes": { + "0.4.10": "0.2.0" + } + } + ], + "numpy": [ + "numpy" + ], + "paddlepaddle": [ + "paddlepaddle" + ], + "mxnet": [ + "mxnet" + ], + "torch": [ + "torchvision" + ] } diff --git a/docs/demos b/docs/demos index 98870b7b92546..fa1b41aa88a6c 160000 --- a/docs/demos +++ b/docs/demos @@ -1 +1 @@ -Subproject commit 98870b7b92546a9e1dc9b45a0042771bd3c7b505 +Subproject commit fa1b41aa88a6cc4fd6ccbac955b84797c61cb741 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..ecac3e965614c --- /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/badges/badge_01-00.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_01-02.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_01-03.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_01-04.png + :width: 110 + :alt: Alternative text + * - Merging Master + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_04-00.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_04-02.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_04-03.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_04-04.png + :width: 110 + :alt: Alternative text + * - Merging Wizard + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_05-00.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_05-02.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_05-03.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_05-04.png + :width: 110 + :alt: Alternative text + * - Ivy Inspectors + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_06-00.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_06-02.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/badges/badge_06-03.png + :width: 110 + :alt: Alternative text + - .. image:: https://raw.githubusercontent.com/unifyai/ivy/main/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 0b6c0535dbc93..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: @@ -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 6a7565ec335f0..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. @@ -129,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 f3cb6defae24b..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.2 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 6ccccad5696f6..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 @@ -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..7b951caecf020 --- /dev/null +++ b/docs/overview/volunteer_ranks.rst @@ -0,0 +1,170 @@ +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 + * - Bhushan Srivastava + - `he11owthere `_ + - Merging Master, Ivy Inspector, OG Gold + * - Edward Amimo + - `mobley-trent `_ + - Merging Master, Ivy Inspector, OG Gold + * - Ogban Ugot + - `ogbanugot `_ + - Merging Master, Ivy Inspector, OG Gold + * - Fayad Alman + - `Fayad-Alman `_ + - Ivy Inspector, OG Gold + * - sarvesh kesharwani + - `Sarvesh-Kesharwani `_ + - Ivy Inspector Bronze, OG Gold + * - Krishna Boppana + - `krishna-boppana `_ + - OG Gold + * - Saptarshi Bandopadhyay + - `Saptarshi-Bandopadhyay `_ + - OG Gold + * - Tugay GΓΌl + - `sondertg `_ + - OG Gold + * - Vismay Suramwar + - `leacornelio `_ + - OG Gold + * - samunder singh + - `samthakur587 `_ + - Merging Master Gold, Merging Wizard, Ivy Inspector Gold + * - V\. Sai Suraj + - `Sai-Suraj-27 `_ + - Merging Master Gold, Ivy Inspector Bronze + * - Zheng Jay Choy + - `ZJay07 `_ + - Merging Master Gold, Ivy Inspector +Rising Contributors +------------------- +.. list-table:: + :widths: 50 50 50 + :header-rows: 1 + + * - Name + - Github ID + - Badges + * - Ebenezer Gadri-Akrong + - `aibenStunner `_ + - Merging Master, Ivy Inspector, OG Silver + * - nitesh kesharwani + - `NiteshK84 `_ + - Ivy Inspector Bronze, OG Silver + * - Abdullah Sabry + - `abdullahsabry `_ + - OG Silver + * - 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 + * - Mohamed Ibrahim + - `Medo072 `_ + - Merging Master, OG Bronze + * - Sheroz Khan + - `ksheroz `_ + - Merging Master, OG Bronze + * - Suyash Gupta + - `sgalpha01 `_ + - Debugging Dynamo, Merging Master Bronze, Merging Wizard Bronze + * - Alvin Vinod + - `alvin-98 `_ + - OG Bronze + * - David Adlai Nettey + - `Adlai-1 `_ + - Merging Master Bronze, Ivy Inspector + * - Mwape Bunda + - `teckno `_ + - OG Bronze + * - Ramya Manasa Amancherla + - `ramyamanasa `_ + - Merging Master Bronze, Ivy Inspector + * - Rohit Kumar Salla + - `rohitsalla `_ + - Merging Master Bronze, Ivy Inspector Bronze + * - Sanjay Suthar + - `Sanjay8602 `_ + - Merging Master Bronze, Ivy Inspector Bronze + * - Syed Muzakkir Hussain + - `muzakkirhussain011 `_ + - Merging Master Bronze, Ivy Inspector + * - Chaitanya Lakhchaura + - `ZenithFlux `_ + - Merging Master Bronze + * - Kacper KoΕΌdoΕ„ + - `Kacper-W-Kozdon `_ + - Merging Master Bronze + * - R E Zera Marveen Lyngkhoi + - `fleventy-5 `_ + - Merging Master Bronze +Contributors +------------ +.. list-table:: + :widths: 50 50 50 + :header-rows: 1 + + * - Name + - Github ID + - Badges + * - Jackson McClintock + - `jacksondm33 `_ + - Merging Master, Merging Wizard, Ivy Inspector + * - Ayush Lokare + - `ayush111111 `_ + - 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 + * - Rahul Prem + - `rp097 `_ + - Merging Master, Ivy Inspector + * - Vaishnavi Mudaliar + - `VaishnaviMudaliar `_ + - Merging Master, Ivy Inspector + * - Waqar Ahmed + - `waqaarahmed `_ + - Merging Master, Ivy Inspector + * - Aryan Pandey + - `Aryan8912 `_ + - Merging Master + * - Dhruv Sharma + - `druvdub `_ + - Merging Master + * - Mehmet Bilgehan Bezcioglu + - `BilgehanMehmet `_ + - Merging Master + * - Omkar khade + - `Omickeyee `_ + - Merging Master + * - Purity Nyagweth + - `Purity-E `_ + - Merging Master + * - Stefan Sanchez + - `StefanSan26 `_ + - Merging Master diff --git a/install_dependencies.sh b/install_dependencies.sh index 6fa84d7003008..911662965c6e3 100755 --- a/install_dependencies.sh +++ b/install_dependencies.sh @@ -1,6 +1,6 @@ # This shell script is required by the doc-builder. Moving it might break # the doc-building pipeline - +pip install -e . pip install -r requirements/requirements.txt if [[ $(arch) == 'arm64' ]]; then brew install pandoc diff --git a/ivy/__init__.py b/ivy/__init__.py index 7f24a893c3d60..e5c5644307178 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 @@ -282,67 +287,40 @@ 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__() - - def __div__(self, other): - return self._shape // other - - def __floordiv__(self, other): - return self._shape // other - - def __mod__(self, other): - return self._shape % other - - def __rdiv__(self, other): - return other // self._shape - - def __rmod__(self, other): - return other % self._shape + if ivy.current_backend_str() == "tensorflow": + return builtins.bool(builtins.tuple(self._shape)) + return builtins.bool(self._shape) def __reduce__(self): - return (self._shape,) + return (self.__class__, (self._shape,)) def as_dimension(self, other): if isinstance(other, self._shape): - return other + return to_ivy(other) else: return self._shape - def __sub__(self, other): - try: - self._shape = self._shape - other - except TypeError: - self._shape = self._shape - list(other) - return self - - def __rsub__(self, other): - try: - self._shape = other - self._shape - except TypeError: - self._shape = list(other) - self._shape - return self - def __eq__(self, other): self._shape = Shape._shape_casting_helper(self._shape, other) return self._shape == other - def __int__(self): - if hasattr(self._shape, "__int__"): - res = self._shape.__int__() - else: - res = int(self._shape) - if res is NotImplemented: - return res - return to_ivy(res) - def __ge__(self, other): self._shape = Shape._shape_casting_helper(self._shape, other) return self._shape >= other @@ -364,7 +342,7 @@ def __getattribute__(self, item): def __getitem__(self, key): try: - return self._shape[key] + return to_ivy(self._shape[key]) except (TypeError, IndexError): return None @@ -383,6 +361,17 @@ def __sizeof__(self): def __dir__(self): return self._shape.__dir__() + def __getnewargs__(self): + if self._shape is None: + raise ivy.utils.exceptions.IvyException( + "Cannot calculate the number of elements in a partially known Shape" + ) + return ( + builtins.tuple( + self._shape, + ), + ) + @property def shape(self): return self._shape @@ -402,11 +391,11 @@ def index(self, index): if self._shape.rank is None: return Shape(None) else: - return self._shape[index] + return to_ivy(self._shape[index]) def as_dimension(self): if isinstance(self._shape, Shape): - return self._shape + return to_ivy(self._shape) else: return Shape(self._shape) @@ -429,6 +418,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") @@ -442,8 +432,8 @@ def unknown_shape(rank=None, **kwargs): def with_rank(self, rank): try: return self.merge_with(self.unknown_shape(rank=rank)) - except ValueError: - raise ValueError(f"Shape {self} must have 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: @@ -457,6 +447,7 @@ def with_rank_at_most(self, rank): else: return self + @staticmethod def as_shape(shape): if isinstance(shape, Shape): return shape @@ -497,6 +488,25 @@ def as_list(self): ) return list(self._shape) + def numel(self): + if self._shape is None: + raise ivy.utils.exceptions.IvyException( + "Cannot calculate the number of elements in a partially known Shape" + ) + return ivy.prod(self.as_list(), dtype=ivy.int64).to_scalar() + + def __concat__(self, other): + return self.concatenate(other) + + def flatten(self): + # check https://github.com/tensorflow/tensorflow/blob/0d2d8a66fca1cbcdd6dd4e0cd6971792782e6844/tensorflow/python/framework/tensor_shape.py#L1299 # noqa: E501 + return [] + + def to_tensors(self, value): + # check https://github.com/tensorflow/tensorflow/blob/0d2d8a66fca1cbcdd6dd4e0cd6971792782e6844/tensorflow/python/framework/tensor_shape.py#L1294 # noqa: E501 + del value + return [] + class IntDtype(Dtype): def __new__(cls, dtype_str): @@ -589,7 +599,7 @@ class Node(str): nan_policy_stack = [] dynamic_backend_stack = [] warn_to_regex = {"all": "!.*", "ivy_only": "^(?!.*ivy).*$", "none": ".*"} - +cython_wrappers_stack = [] # local import threading @@ -739,7 +749,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 * @@ -774,6 +784,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 @@ -793,9 +804,13 @@ class Node(str): except: # noqa: E722 pass try: - from .compiler.compiler import transpile, trace_graph, unify + from .compiler.compiler import source_to_source, 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(): @@ -918,44 +933,47 @@ def __deepcopy__(self, memo): # defines ivy.globals attribute -globals_vars = GlobalsDict({ - "backend_stack": backend_stack, - "default_device_stack": device.default_device_stack, - "valid_dtypes": valid_dtypes, - "valid_numeric_dtypes": valid_numeric_dtypes, - "valid_int_dtypes": valid_int_dtypes, - "valid_uint_dtypes": valid_uint_dtypes, - "valid_complex_dtypes": valid_complex_dtypes, - "valid_devices": valid_devices, - "invalid_dtypes": invalid_dtypes, - "invalid_numeric_dtypes": invalid_numeric_dtypes, - "invalid_int_dtypes": invalid_int_dtypes, - "invalid_float_dtypes": invalid_float_dtypes, - "invalid_uint_dtypes": invalid_uint_dtypes, - "invalid_complex_dtypes": invalid_complex_dtypes, - "invalid_devices": invalid_devices, - "array_significant_figures_stack": array_significant_figures_stack, - "array_decimal_values_stack": array_decimal_values_stack, - "warning_level_stack": warning_level_stack, - "queue_timeout_stack": general.queue_timeout_stack, - "array_mode_stack": general.array_mode_stack, - "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, - "min_denominator_stack": general.min_denominator_stack, - "min_base_stack": general.min_base_stack, - "tmp_dir_stack": general.tmp_dir_stack, - "precise_mode_stack": general.precise_mode_stack, - "nestable_mode_stack": general.nestable_mode_stack, - "exception_trace_mode_stack": general.exception_trace_mode_stack, - "default_dtype_stack": data_type.default_dtype_stack, - "default_float_dtype_stack": data_type.default_float_dtype_stack, - "default_int_dtype_stack": data_type.default_int_dtype_stack, - "default_uint_dtype_stack": data_type.default_uint_dtype_stack, - "nan_policy_stack": nan_policy_stack, - "dynamic_backend_stack": dynamic_backend_stack, -}) +globals_vars = GlobalsDict( + { + "backend_stack": backend_stack, + "default_device_stack": device.default_device_stack, + "valid_dtypes": valid_dtypes, + "valid_numeric_dtypes": valid_numeric_dtypes, + "valid_int_dtypes": valid_int_dtypes, + "valid_uint_dtypes": valid_uint_dtypes, + "valid_complex_dtypes": valid_complex_dtypes, + "valid_devices": valid_devices, + "invalid_dtypes": invalid_dtypes, + "invalid_numeric_dtypes": invalid_numeric_dtypes, + "invalid_int_dtypes": invalid_int_dtypes, + "invalid_float_dtypes": invalid_float_dtypes, + "invalid_uint_dtypes": invalid_uint_dtypes, + "invalid_complex_dtypes": invalid_complex_dtypes, + "invalid_devices": invalid_devices, + "array_significant_figures_stack": array_significant_figures_stack, + "array_decimal_values_stack": array_decimal_values_stack, + "warning_level_stack": warning_level_stack, + "queue_timeout_stack": general.queue_timeout_stack, + "array_mode_stack": general.array_mode_stack, + "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, + "min_denominator_stack": general.min_denominator_stack, + "min_base_stack": general.min_base_stack, + "tmp_dir_stack": general.tmp_dir_stack, + "precise_mode_stack": general.precise_mode_stack, + "nestable_mode_stack": general.nestable_mode_stack, + "exception_trace_mode_stack": general.exception_trace_mode_stack, + "default_dtype_stack": data_type.default_dtype_stack, + "default_float_dtype_stack": data_type.default_float_dtype_stack, + "default_int_dtype_stack": data_type.default_int_dtype_stack, + "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, + } +) _default_globals = copy.deepcopy(globals_vars) @@ -1008,8 +1026,7 @@ def vec_sig_fig(x, sig_fig=3): def set_array_significant_figures(sig_figs): - """ - Summary. + """Summary. Parameters ---------- @@ -1049,8 +1066,7 @@ def _assert_array_decimal_values_formatting(dec_vals): def set_array_decimal_values(dec_vals): - """ - Summary. + """Summary. Parameters ---------- @@ -1076,8 +1092,7 @@ def unset_array_decimal_values(): def set_warning_level(warn_level): - """ - Summary. + """Summary. Parameters ---------- @@ -1109,8 +1124,7 @@ def warn(warning_message, stacklevel=0): def set_nan_policy(warn_level): - """ - Summary. + """Summary. Parameters ---------- @@ -1142,8 +1156,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 +1167,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 +1178,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 +1256,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 +1481,7 @@ def cast_data_types(val=True): "default_int_dtype", "default_complex_dtype", "default_uint_dtype", + "cython_wrappers_mode", ] @@ -1462,8 +1511,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 +1523,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 +1546,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..488bc026d0220 100644 --- a/ivy/_version.py +++ b/ivy/_version.py @@ -1 +1 @@ -__version__ = "0.0.4.0" +__version__ = "0.0.9.4" diff --git a/ivy/compiler/compiler.py b/ivy/compiler/compiler.py index 97f8ada162541..fb1ba085e9820 100644 --- a/ivy/compiler/compiler.py +++ b/ivy/compiler/compiler.py @@ -1,4 +1,39 @@ -from typing import Callable, Optional, List, Union, Iterable, Tuple, Mapping +from typing import Callable, Optional, List, Union, Iterable, Sequence, Mapping + + +def source_to_source( + object, + source: str = "torch", + target: str = "torch_frontend", + profiling: bool = False, +): + """Converts a given object (class/function) from one framework to another. + + This function performs source-to-source translation of a given object from the source framework + to the target framework. + + The object can be translated between two frameworks or in-between the Ivy IR + as well e.g. (source="torch_frontend", target="ivy") or (source="torch_frontend", target="tensorflow") etc. + + Args: + ---- + object: The object (class/function) to be translated. + source (str, optional): The source framework. Defaults to 'torch'. + target (str, optional): The target framework. Defaults to 'torch_frontend'. + profiling: Whether to add performance profiling. + + Returns: + ------- + The translated object. + """ + from ._compiler import source_to_source as _source_to_source + + return _source_to_source( + object=object, + source=source, + target=target, + profiling=profiling, + ) def trace_graph( @@ -10,18 +45,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, - graph_caching: bool = False, - args: Optional[Tuple] = None, + compile_mode: Optional[str] = None, + graph_caching: bool = True, + args: Optional[Sequence] = None, kwargs: Optional[Mapping] = None, params_v=None, v=None ): - """ - Take `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 +73,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 @@ -101,10 +140,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, @@ -121,19 +161,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, - graph_caching: bool = False, + compile_mode: Optional[str] = None, + graph_caching: bool = True, + 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 ---------- @@ -162,8 +204,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, @@ -177,20 +221,25 @@ def transpile( def unify( *objs: Callable, source: Optional[str] = None, - graph_caching: bool = False, - args: Optional[Tuple] = None, + graph_caching: bool = True, + 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 06b5cb4d4615a..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): @@ -232,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 ------- @@ -261,16 +260,7 @@ def shape(self) -> ivy.Shape: @property def size(self) -> Optional[int]: """Number of elements in the array.""" - if self._size is None: - if ivy.current_backend_str() in ["numpy", "jax"]: - self._size = self._data.size - return self._size - 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]: @@ -290,8 +280,7 @@ def strides(self) -> Optional[int]: @property def T(self) -> ivy.Array: - """ - Transpose of the array. + """Transpose of the array. Returns ------- @@ -309,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 ------- @@ -323,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 ------- @@ -351,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 @@ -384,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) @@ -403,7 +390,13 @@ def __repr__(self): self._post_repr = ")" sig_fig = ivy.array_significant_figures dec_vals = ivy.array_decimal_values - backend = ivy.with_backend(self.backend) + if self.backend == "" or ivy.is_local(): + # If the array was constructed using implicit backend + backend = ivy.current_backend() + else: + # Requirerd in the case that backend is different + # from the currently set backend + backend = ivy.with_backend(self.backend) arr_np = backend.to_numpy(self._data) rep = ( np.array(ivy.vec_sig_fig(arr_np, sig_fig)) @@ -479,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 ---------- @@ -521,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 ---------- @@ -551,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 ---------- @@ -584,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 ---------- @@ -616,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 ---------- @@ -673,10 +661,9 @@ def __rdivmod__(self, other): 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 ---------- @@ -727,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 ---------- @@ -803,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 ---------- @@ -833,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 ---------- @@ -863,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 ---------- @@ -901,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 ---------- @@ -939,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 ---------- @@ -986,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 ---------- @@ -1054,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 ---------- @@ -1112,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 ---------- @@ -1145,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 2020b1f2306c4..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. @@ -141,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 ---------- @@ -173,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 ---------- @@ -205,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 ---------- @@ -248,9 +246,9 @@ def args_to_native( 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 ---------- @@ -296,11 +294,10 @@ def to_new_backend( 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``. + """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 ---------- @@ -342,14 +339,13 @@ def args_to_new_backend( *args: Iterable[Any], native: bool = True, shallow: bool = True, - 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 the new current backend framework for all nested - ivy.Array, ivy.NativeArray or NativeVariable instances. + """Return args and keyword args in the new current backend framework for + all nested ivy.Array, ivy.NativeArray or NativeVariable instances. Parameters ---------- 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 24e38a9dc52ff..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 ---------- @@ -369,10 +359,9 @@ def threshold( 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. + """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 ---------- @@ -407,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 ---------- @@ -448,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 ---------- @@ -488,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 ---------- @@ -537,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 ---------- @@ -569,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 fdca1bcffabf3..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 @@ -270,8 +265,8 @@ def unsorted_segment_mean( 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. + """Compute the mean of values in the array 'self' based on segment + identifiers. Parameters ---------- @@ -318,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. @@ -335,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 @@ -347,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 2e1bb60a33d05..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 ---------- @@ -957,8 +955,7 @@ def fft2( 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 ---------- @@ -1150,8 +1145,7 @@ def rfftn( 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 ---------- @@ -1295,8 +1287,8 @@ def max_unpool1d( 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 f7027eafa78ab..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 -------- @@ -222,10 +217,9 @@ def rot90( 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. @@ -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 87d5bae046c94..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 ---------- @@ -277,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 ---------- @@ -331,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 ---------- @@ -371,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 ---------- @@ -433,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 ---------- @@ -495,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 ---------- @@ -540,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 ---------- @@ -576,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 ---------- @@ -605,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 ---------- @@ -640,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 ---------- @@ -677,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 ---------- @@ -719,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 ---------- @@ -770,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 ---------- @@ -805,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 ---------- @@ -845,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 ---------- @@ -879,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 ---------- @@ -915,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 ---------- @@ -979,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 ---------- @@ -1023,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 ---------- @@ -1061,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 ---------- @@ -1107,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 ---------- @@ -1152,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 ---------- @@ -1220,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 ---------- @@ -1261,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 ---------- @@ -1303,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 ---------- @@ -1351,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 ---------- @@ -1396,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..a4a8aa9609f2a 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.dropout1d 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.dropout1d 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.dropout3d 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..0387ec59b3456 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 ---------- @@ -461,12 +453,12 @@ 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: - """ - 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 ---------- @@ -481,6 +473,10 @@ 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 + performingthe 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. @@ -504,7 +500,7 @@ def matrix_norm( [[11.4 ]]]) """ return ivy.matrix_norm( - self._data, ord=ord, axis=axis, keepdims=keepdims, out=out + self._data, ord=ord, axis=axis, keepdims=keepdims, dtype=dtype, out=out ) def matrix_power( @@ -525,10 +521,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 +594,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 +631,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 +667,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 +711,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 +770,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 +826,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 +913,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 +985,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 +1077,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..262dc2371b705 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 ---------- @@ -137,15 +149,15 @@ def max( def mean( self: ivy.Array, /, - *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + *, + dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, 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** @@ -170,6 +182,10 @@ def mean( compatible with the input array (see :ref:`broadcasting`). Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. + dtype + the desired data type of returned tensor. If specified, the input tensor + is casted to dtype before the operation is performed. This is useful for + preventing data type overflows. Default: None. out optional output array, for writing the result to. @@ -219,7 +235,7 @@ def mean( >>> print(y) ivy.array([1., 4.]) """ - return ivy.mean(self._data, axis=axis, keepdims=keepdims, out=out) + return ivy.mean(self._data, axis=axis, keepdims=keepdims, dtype=dtype, out=out) def var( self: ivy.Array, @@ -230,10 +246,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 +331,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 +416,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 +510,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 +584,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 +654,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 b2bc127c40863..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 ---------- @@ -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 ---------- @@ -930,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 ---------- @@ -983,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 ---------- @@ -1038,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 ---------- @@ -1080,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 ---------- @@ -1098,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 ---------- @@ -1142,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 ---------- @@ -1171,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 @@ -1193,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 ---------- @@ -1216,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 ---------- @@ -1237,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 ---------- @@ -1256,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 @@ -1279,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 ---------- @@ -1299,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): @@ -1320,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 ---------- @@ -1363,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 ---------- @@ -1388,20 +1367,21 @@ def cont_flatten_key_chain( if below_depth and num_keys > below_depth: pre_keys = flat_keys[0:below_depth] del flat_keys[0:below_depth] - return "/".join([ - k - for k in [ - "/".join(pre_keys), - replacement.join(flat_keys), - "/".join(post_keys), + return "/".join( + [ + k + for k in [ + "/".join(pre_keys), + replacement.join(flat_keys), + "/".join(post_keys), + ] + if k ] - if k - ]) + ) @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 ---------- @@ -1510,9 +1490,9 @@ def _cont_get_shape(self): if not sub_shapes: return sub_shapes min_num_dims = min(len(sub_shape) for sub_shape in sub_shapes) - sub_shapes_array = np.asarray([ - sub_shape[0:min_num_dims] for sub_shape in sub_shapes - ]) + sub_shapes_array = np.asarray( + [sub_shape[0:min_num_dims] for sub_shape in sub_shapes] + ) sub_shapes_array = np.where(sub_shapes_array == 0, -1, sub_shapes_array) mask = np.prod(sub_shapes_array / sub_shapes_array[0:1], 0) == 1 # noinspection PyTypeChecker @@ -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 ---------- @@ -1720,16 +1699,18 @@ def cont_all_true( Boolean, whether all entries are boolean True. """ return bool( - np.prod([ - v - for k, v in self.cont_as_bools( - assert_is_bool, - key_chains, - to_apply, - prune_unapplied, - map_sequences, - ).cont_to_iterator() - ]) + np.prod( + [ + v + for k, v in self.cont_as_bools( + assert_is_bool, + key_chains, + to_apply, + prune_unapplied, + map_sequences, + ).cont_to_iterator() + ] + ) ) def cont_all_false( @@ -1740,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 ---------- @@ -1765,21 +1746,22 @@ def cont_all_false( Boolean, whether all entries are boolean False. """ return not bool( - np.sum([ - v - for k, v in self.cont_as_bools( - assert_is_bool, - key_chains, - to_apply, - prune_unapplied, - map_sequences, - ).cont_to_iterator() - ]) + np.sum( + [ + v + for k, v in self.cont_as_bools( + assert_is_bool, + key_chains, + to_apply, + prune_unapplied, + map_sequences, + ).cont_to_iterator() + ] + ) ) def cont_slice_via_key(self, slice_key): - """ - Get slice of container, based on key. + """Get slice of container, based on key. Parameters ---------- @@ -1808,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 ---------- @@ -1848,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 ---------- @@ -1896,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. @@ -1952,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 ---------- @@ -1969,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 ---------- @@ -2006,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 ---------- @@ -2030,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 @@ -2066,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 ---------- @@ -2096,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 ---------- @@ -2117,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 ------- @@ -2140,8 +2116,7 @@ def cont_to_raw(self): return return_item def cont_to_dict(self): - """ - Summary. + """Summary. Returns ------- @@ -2195,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) @@ -2235,8 +2210,7 @@ def cont_to_iterator_keys( yield kc def cont_to_flat_list(self): - """ - Summary. + """Summary. Returns ------- @@ -2246,9 +2220,8 @@ def cont_to_flat_list(self): 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 ---------- @@ -2269,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 ---------- @@ -2304,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 ---------- @@ -2327,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 ---------- @@ -2359,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 ---------- @@ -2378,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 ---------- @@ -2409,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 ---------- @@ -2454,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 ---------- @@ -2474,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 ---------- @@ -2514,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 ---------- @@ -2558,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 ---------- @@ -2585,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 ---------- @@ -2651,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 ---------- @@ -2675,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 ---------- @@ -2706,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 ---------- @@ -2751,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 ---------- @@ -2783,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 ---------- @@ -2824,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 ---------- @@ -2865,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 ---------- @@ -2900,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 ---------- @@ -2930,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 ---------- @@ -2956,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 ---------- @@ -2987,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 ---------- @@ -3029,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 ---------- @@ -3077,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 ---------- @@ -3101,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 ---------- @@ -3140,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 ---------- @@ -3163,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 ------- @@ -3173,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 """ @@ -3197,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 ---------- @@ -3273,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 ---------- @@ -3336,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 ---------- @@ -3369,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 ---------- @@ -3386,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 ---------- @@ -3399,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 ---------- @@ -3412,8 +3357,7 @@ def cont_try_kc(self, key): return self def cont_cutoff_at_depth(self, depth_cutoff, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3438,8 +3382,7 @@ def _maybe_cutoff(cont, kc): return ret def cont_cutoff_at_height(self, height_cutoff, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3478,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 ---------- @@ -3510,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 ---------- @@ -3532,8 +3473,7 @@ def _update_print_limit(cont, _): # noinspection PyTypeChecker def cont_remove_print_limit(self, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3543,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 ---------- @@ -3564,8 +3503,7 @@ def _update_key_length_limit(cont, _): return ret def cont_remove_key_length_limit(self, inplace=False): - """ - Summary. + """Summary. Parameters ---------- @@ -3575,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 ---------- @@ -3596,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 ---------- @@ -3617,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 ---------- @@ -3638,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 ---------- @@ -3662,8 +3596,7 @@ def cont_show(self): # noinspection PyUnresolvedReferences def cont_show_sub_container(self, sub_cont_or_keychain): - """ - Summary. + """Summary. Parameters ---------- @@ -3730,9 +3663,9 @@ def cont_show_sub_container(self, sub_cont_or_keychain): # prepend these lines to the sub-container sub_repr = ( "\n" - + "\n".join([ - " " * num_spaces_to_add + s for s in sub_repr[1:-1].split("\n") - ]) + + "\n".join( + [" " * num_spaces_to_add + s for s in sub_repr[1:-1].split("\n")] + ) + "\n" ) @@ -3767,10 +3700,12 @@ def _pre_pad_alpha_line(str_in): padded = True return "\\n" + indent_str + indented_key_str + str_in - leading_str_to_keep = ", ".join([ - _pre_pad_alpha_line(s) if s[0].isalpha() and i != 0 else s - for i, s in enumerate(leading_str_to_keep.split(", ")) - ]) + leading_str_to_keep = ", ".join( + [ + _pre_pad_alpha_line(s) if s[0].isalpha() and i != 0 else s + for i, s in enumerate(leading_str_to_keep.split(", ")) + ] + ) local_indent_str = "" if padded else indent_str leading_str = leading_str_to_keep.split("\\n")[-1].replace('"', "") remaining_str = array_str_in_split[1] @@ -3787,30 +3722,32 @@ def _pre_pad_alpha_line(str_in): uniform_indent_wo_overflow_list = list( filter(None, uniform_indent_wo_overflow.split("\\n")) ) - uniform_indent = "\n".join([ - ( - local_indent_str + extra_indent + " " + s - if ( - s[0].isnumeric() - or s[0] == "-" - or s[0:3] == "..." - or max(ss in s[0:6] for ss in ["nan, ", "inf, "]) - ) - else ( - indent_str + indented_key_str + s - if (not s[0].isspace() and s[0] != '"') - else s + uniform_indent = "\n".join( + [ + ( + local_indent_str + extra_indent + " " + s + if ( + s[0].isnumeric() + or s[0] == "-" + or s[0:3] == "..." + or max(ss in s[0:6] for ss in ["nan, ", "inf, "]) + ) + else ( + indent_str + indented_key_str + s + if (not s[0].isspace() and s[0] != '"') + else s + ) ) - ) - for s in uniform_indent_wo_overflow_list - ]) + for s in uniform_indent_wo_overflow_list + ] + ) indented = uniform_indent # 10 dimensions is a sensible upper bound for the number in a single array for i in range(2, 10): indented = indented.replace(" " * (i - 1) + "[" * i, "[" * i) - indented = "\n".join([ - s for s in indented.split("\n") if bool(s) and not s.isspace() - ]) + indented = "\n".join( + [s for s in indented.split("\n") if bool(s) and not s.isspace()] + ) return indented def _align_arrays(str_in): @@ -3909,27 +3846,32 @@ def _align_arrays(str_in): def _add_newline(str_in): str_in_split = str_in.split("\n") str_split_size = len(str_in_split) - return "\n".join([ - ( - ("\n" * self._print_line_spacing + ss) - if i == (str_split_size - 1) - else ss - ) - for i, ss in enumerate(str_in_split) - ]) + return "\n".join( + [ + ( + ("\n" * self._print_line_spacing + ss) + if i == (str_split_size - 1) + else ss + ) + for i, ss in enumerate(str_in_split) + ] + ) - json_dumped_str = '":'.join([ - _add_newline(s) for s in json_dumped_str.split('":') - ]) + json_dumped_str = '":'.join( + [_add_newline(s) for s in json_dumped_str.split('":')] + ) # improve tf formatting if ivy.backend_stack and ivy.current_backend_str() == "tensorflow": json_dumped_str_split = json_dumped_str.split("'Variable:") json_dumped_str = ( json_dumped_str_split[0] + ", " - + ", ".join([ - "'".join(ss.split("'")[1:]) for ss in json_dumped_str_split[1:] - ]) + + ", ".join( + [ + "'".join(ss.split("'")[1:]) + for ss in json_dumped_str_split[1:] + ] + ) ) json_dumped_str = ( json_dumped_str.replace(":shape", ", shape") @@ -3940,24 +3882,26 @@ def _add_newline(str_in): # color keys json_dumped_str_split = json_dumped_str.split('":') split_size = len(json_dumped_str_split) - json_dumped_str = '":'.join([ - ( - ' "'.join( - sub_str.split(' "')[:-1] - + [ - termcolor.colored( - ivy.Container.cont_trim_key( - sub_str.split(' "')[-1], self._key_length_limit - ), - self._default_key_color, - ) - ] + json_dumped_str = '":'.join( + [ + ( + ' "'.join( + sub_str.split(' "')[:-1] + + [ + termcolor.colored( + ivy.Container.cont_trim_key( + sub_str.split(' "')[-1], self._key_length_limit + ), + self._default_key_color, + ) + ] + ) + if i < split_size - 1 + else sub_str ) - if i < split_size - 1 - else sub_str - ) - for i, sub_str in enumerate(json_dumped_str_split) - ]) + for i, sub_str in enumerate(json_dumped_str_split) + ] + ) # remove quotation marks, shape tuple, and color other elements of the dict ret = ( json_dumped_str.replace('"', "") @@ -3980,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): @@ -4007,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): @@ -4053,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 ---------- @@ -4095,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 ---------- @@ -4205,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. @@ -4215,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. """ @@ -4224,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. """ @@ -4233,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. """ @@ -4242,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. """ diff --git a/ivy/data_classes/container/container.py b/ivy/data_classes/container/container.py index b41def052fd73..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 83ec6aafc6884..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 ---------- diff --git a/ivy/data_classes/container/data_type.py b/ivy/data_classes/container/data_type.py index c8d7533d64006..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 @@ -162,10 +160,10 @@ def _static_broadcast_arrays( 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 ---------- @@ -238,10 +236,10 @@ def broadcast_arrays( 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 c52a3f42ba646..8932ae067e331 100644 --- a/ivy/data_classes/container/elementwise.py +++ b/ivy/data_classes/container/elementwise.py @@ -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 ---------- @@ -78,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 ---------- @@ -140,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 ---------- @@ -202,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 ---------- @@ -265,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 ---------- @@ -329,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 ---------- @@ -428,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 ---------- @@ -490,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 ---------- @@ -569,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 ---------- @@ -640,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 ---------- @@ -712,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 ---------- @@ -774,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 ---------- @@ -837,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 ---------- @@ -897,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 ---------- @@ -959,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 ---------- @@ -1040,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 ---------- @@ -1119,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 ---------- @@ -1180,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 ---------- @@ -1243,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 ---------- @@ -1328,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 ---------- @@ -1397,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 ---------- @@ -1455,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 ---------- @@ -1511,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 ---------- @@ -1578,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 ---------- @@ -1648,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 ---------- @@ -1711,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 ---------- @@ -1776,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 ---------- @@ -1853,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 ---------- @@ -1920,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 ---------- @@ -2001,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 ---------- @@ -2068,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 ---------- @@ -2137,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 ---------- @@ -2205,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 ---------- @@ -2265,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 ---------- @@ -2326,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 ---------- @@ -2399,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 ---------- @@ -2474,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 ---------- @@ -2544,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 ---------- @@ -2626,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 ---------- @@ -2695,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 ---------- @@ -2776,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 ---------- @@ -2841,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 ---------- @@ -2899,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 ---------- @@ -2948,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 ---------- @@ -2995,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 ---------- @@ -3056,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 ---------- @@ -3113,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 ---------- @@ -3162,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 ---------- @@ -3206,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 ---------- @@ -3250,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 ---------- @@ -3291,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 ---------- @@ -3351,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 ---------- @@ -3412,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 ---------- @@ -3473,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 ---------- @@ -3543,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 ---------- @@ -3603,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 ---------- @@ -3665,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 ---------- @@ -3746,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 ---------- @@ -3828,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 ---------- @@ -3877,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 ---------- @@ -3922,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 ---------- @@ -3991,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 ---------- @@ -4060,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 ---------- @@ -4129,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 ---------- @@ -4197,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 ---------- @@ -4258,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 ---------- @@ -4322,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 ---------- @@ -4393,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 ---------- @@ -4463,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 ---------- @@ -4526,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 ---------- @@ -4589,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 ---------- @@ -4658,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 ---------- @@ -4727,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 ---------- @@ -4796,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 ---------- @@ -4875,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 ---------- @@ -4940,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 ---------- @@ -5006,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 ---------- @@ -5074,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 ---------- @@ -5136,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 ---------- @@ -5201,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 ---------- @@ -5267,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 ---------- @@ -5332,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 ---------- @@ -5399,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 ---------- @@ -5471,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 ---------- @@ -5543,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 ---------- @@ -5592,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 ---------- @@ -5637,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 ---------- @@ -5725,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 ---------- @@ -5811,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 ---------- @@ -5871,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 ---------- @@ -5942,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 ---------- @@ -6011,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 ---------- @@ -6091,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 ---------- @@ -6171,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 ---------- @@ -6238,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 ---------- @@ -6310,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 ---------- @@ -6393,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 ---------- @@ -6455,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 ---------- @@ -6519,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 ---------- @@ -6588,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 ---------- @@ -6667,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 ---------- @@ -6729,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 ---------- @@ -6793,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 ---------- @@ -6861,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 ---------- @@ -6928,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 ---------- @@ -6990,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 ---------- @@ -7055,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 ---------- @@ -7151,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 ---------- @@ -7246,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 ---------- @@ -7312,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 ---------- @@ -7379,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 ---------- @@ -7441,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 ---------- @@ -7505,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 ---------- @@ -7567,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 ---------- @@ -7630,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 ---------- @@ -7701,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 ---------- @@ -7773,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 ---------- @@ -7833,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 ---------- @@ -7894,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 ---------- @@ -7957,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 ---------- @@ -8023,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 ---------- @@ -8103,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 ---------- @@ -8181,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 ---------- @@ -8242,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 ---------- @@ -8305,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 ---------- @@ -8371,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 ---------- @@ -8438,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 ---------- @@ -8500,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 ---------- @@ -8561,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 ---------- @@ -8620,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 ---------- @@ -8682,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 ---------- @@ -8755,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 ---------- @@ -8828,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 ---------- @@ -8906,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 ---------- @@ -8982,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 ---------- @@ -9040,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 ---------- @@ -9099,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 ---------- @@ -9158,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 ---------- @@ -9220,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 ---------- @@ -9279,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 ---------- @@ -9342,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 ---------- @@ -9412,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 ---------- @@ -9482,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 ---------- @@ -9543,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 ---------- @@ -9608,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 ---------- @@ -9666,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 ---------- @@ -9716,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 ---------- @@ -9769,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 1d1cb87018641..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 ---------- @@ -1201,10 +1183,9 @@ def _static_threshold( 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. + """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 ---------- @@ -1267,10 +1248,9 @@ def threshold( 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. + """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 ---------- @@ -1332,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 ---------- @@ -1393,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 ---------- @@ -1454,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 ---------- @@ -1522,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 ---------- @@ -1591,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 ---------- @@ -1678,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 ---------- @@ -1761,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 ---------- @@ -1819,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 ---------- @@ -1848,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) { @@ -1866,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 03a0184d81eaf..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 ---------- @@ -623,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 ---------- @@ -700,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 ---------- @@ -775,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 ---- @@ -830,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 ---- @@ -875,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 ---------- @@ -925,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 ---------- @@ -966,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 ---------- @@ -1018,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 ---------- @@ -1114,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 ---------- @@ -1169,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 ---------- @@ -1211,8 +1195,8 @@ def static_unsorted_segment_mean( 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. + """Compute the mean of values in the input data based on segment + identifiers. Parameters ---------- @@ -1252,65 +1236,13 @@ def static_unsorted_segment_mean( map_sequences=map_sequences, ) - def static_polyval( - coeffs: ivy.Container, - x: Union[ivy.Container, int, float], - *, - key_chains: Optional[Union[List[str], Dict[str, str]]] = None, - to_apply: bool = True, - 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. - - Evaluate and return a polynomial at specific given values. - - Parameters - ---------- - coeffs - Polynomial coefficients (including zero) from highest degree - to constant term. - x - The value of the indeterminate variable at which to evaluate the polynomial. - 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 - Output container containing simplified result of substituing x in the - coefficients - final value of polynomial. - """ - return ContainerBase.cont_multi_map_in_function( - "polyval", - coeffs, - x, - 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. + """Compute the mean of values in the input array or container based on + segment identifiers. Parameters ---------- @@ -1359,15 +1291,65 @@ def unsorted_segment_mean( num_segments, ) + @staticmethod + def static_polyval( + coeffs: ivy.Container, + x: Union[ivy.Container, int, float], + *, + key_chains: Optional[Union[List[str], Dict[str, str]]] = None, + to_apply: bool = True, + 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. + + Evaluate and return a polynomial at specific given values. + + Parameters + ---------- + coeffs + Polynomial coefficients (including zero) from highest degree + to constant term. + x + The value of the indeterminate variable at which to evaluate the polynomial. + 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 + Output container containing simplified result of substituting x in the + coefficients - final value of polynomial. + """ + return ContainerBase.cont_multi_map_in_function( + "polyval", + coeffs, + x, + key_chains=key_chains, + to_apply=to_apply, + prune_unapplied=prune_unapplied, + map_sequences=map_sequences, + ) + def polyval( self: ivy.Container, 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. @@ -1385,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 45cf7674adbb0..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 ---- @@ -3309,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 ---- @@ -3372,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 ---------- @@ -3437,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 @@ -3465,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 ---------- @@ -3518,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 ---------- @@ -3546,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 ce2f0c1ffc3cf..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 ---------- @@ -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 ---------- @@ -2821,8 +2831,8 @@ def max_unpool1d( 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 7d80783f03536..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 ---------- @@ -1048,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 ---------- @@ -1126,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 ---------- @@ -1228,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 ---------- @@ -1320,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 ---------- @@ -1409,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 ---------- @@ -1499,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 ---------- @@ -1563,7 +1545,7 @@ def gather( @staticmethod def _static_has_nans( - self: ivy.Container, + x: ivy.Container, /, *, include_infs: Union[bool, ivy.Container] = True, @@ -1578,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. @@ -1611,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, @@ -1686,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 ---------- @@ -1782,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 ---------- @@ -1877,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 ---------- @@ -1940,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 ---------- @@ -2016,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 ---------- @@ -2083,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 ---------- @@ -2157,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 ---------- @@ -2229,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 ---------- @@ -2312,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 ---------- @@ -2382,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 ---------- @@ -2450,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 ---------- @@ -2531,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 ---------- @@ -2606,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 ---------- @@ -2677,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 ---------- @@ -2750,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 ---------- @@ -2807,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 ---------- @@ -2867,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 ---------- @@ -2920,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 ---------- @@ -2978,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 ---------- @@ -3082,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 ---------- @@ -3168,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 ---------- @@ -3257,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 ---------- @@ -3347,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 ---------- @@ -3435,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 ---------- @@ -3523,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 ---------- @@ -3593,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 ---------- @@ -3660,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 ---------- @@ -3707,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 ---------- @@ -3777,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 ---------- @@ -3854,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 ---------- @@ -3920,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], @@ -3931,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 ---------- @@ -3996,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 ---------- @@ -4070,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 ---------- @@ -4120,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 ---------- @@ -4163,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 ---------- @@ -4191,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 ---------- @@ -4213,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 ---------- @@ -4241,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 ---------- @@ -4268,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 ---------- @@ -4330,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..648ec4c601e2e 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 ---------- @@ -1403,16 +1385,16 @@ def _static_matrix_norm( ord: Union[int, float, Literal[inf, -inf, "fro", "nuc"], ivy.Container] = "fro", axis: Tuple[int, int, ivy.Container] = (-2, -1), keepdims: Union[bool, ivy.Container] = False, + dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, 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 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 ---------- @@ -1427,6 +1409,10 @@ def _static_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 key_chains The key-chains to apply or not apply the method to. Default is ``None``. to_apply @@ -1477,6 +1463,7 @@ def _static_matrix_norm( ord=ord, axis=axis, keepdims=keepdims, + dtype=dtype, key_chains=key_chains, to_apply=to_apply, prune_unapplied=prune_unapplied, @@ -1491,16 +1478,16 @@ def matrix_norm( ord: Union[int, float, Literal[inf, -inf, "fro", "nuc"], ivy.Container] = "fro", axis: Tuple[int, int, ivy.Container] = (-2, -1), keepdims: Union[bool, ivy.Container] = False, + dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype, 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.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 ---------- @@ -1515,6 +1502,10 @@ 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 key_chains The key-chains to apply or not apply the method to. Default is ``None``. to_apply @@ -1565,6 +1556,7 @@ def matrix_norm( ord=ord, axis=axis, keepdims=keepdims, + dtype=dtype, key_chains=key_chains, to_apply=to_apply, prune_unapplied=prune_unapplied, @@ -1630,10 +1622,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 +1716,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 +1805,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 +1861,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 +1916,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 +1990,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 +2062,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 +2157,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 +2250,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 +2321,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 +2440,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 +2512,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 +2729,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 +2822,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 +2963,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 +3077,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 +3227,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 +3294,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 +3360,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 +3432,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..10df0fad279f1 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 ---------- @@ -175,19 +265,19 @@ def max( def mean( self: ivy.Container, /, - *, axis: Optional[Union[int, Sequence[int], ivy.Container]] = None, keepdims: Union[bool, ivy.Container] = False, + *, + dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = 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.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 ---------- @@ -204,6 +294,10 @@ def mean( compatible with the input array (see :ref:`broadcasting`). Otherwise, if ``False``, the reduced axes (dimensions) must not be included in the result. Default: ``False``. + dtype + the desired data type of returned tensor. If specified, the input tensor + is casted to dtype before the operation is performed. This is useful for + preventing data type overflows. Default: None. key_chains The key-chains to apply or not apply the method to. Default is ``None``. @@ -294,7 +388,7 @@ def mean( return self.cont_handle_inplace( self.cont_map( lambda x_, _: ( - ivy.mean(x_, axis=axis, keepdims=keepdims) + ivy.mean(x_, axis=axis, keepdims=keepdims, dtype=dtype) if ivy.is_array(x_) else x_ ), @@ -319,10 +413,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 +530,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 +601,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 +739,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 +930,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 +1079,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 +1220,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 +1376,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 +1467,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/factorized_tensor/tucker_tensor.py b/ivy/data_classes/factorized_tensor/tucker_tensor.py index 0e329f6b54a53..5984be2efe365 100644 --- a/ivy/data_classes/factorized_tensor/tucker_tensor.py +++ b/ivy/data_classes/factorized_tensor/tucker_tensor.py @@ -288,9 +288,9 @@ def validate_tucker_rank( # number of parameters coming from the fixed modes # (these don't have a variable size as a fun of fraction_param) - n_fixed_params = ivy.sum([ - s**2 for _, s in fixed_modes - ]) # size of the factors + n_fixed_params = ivy.sum( + [s**2 for _, s in fixed_modes] + ) # size of the factors n_modes_compressed -= len(fixed_modes) else: n_fixed_params = 0 diff --git a/ivy/data_classes/nested_array/base.py b/ivy/data_classes/nested_array/base.py index 2534a9412706e..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 @@ -139,9 +141,9 @@ def ragged_multi_map(fn, ragged_arrays): args.append(ivy.copy_nest(ragged.data)) ret = ivy.nested_multi_map(lambda x, _: fn(x), args) # infer dtype, shape, and device from the first array in the ret data - broadcasted_shape = ivy.NestedArray.broadcast_shapes([ - arg.shape for arg in ragged_arrays - ]) + broadcasted_shape = ivy.NestedArray.broadcast_shapes( + [arg.shape for arg in ragged_arrays] + ) # infer ragged_rank from broadcasted shape for i, dim in enumerate(broadcasted_shape[::-1]): if dim is None: 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 cbd7c6c2a0702..821594c4fd573 100644 --- a/ivy/func_wrapper.py +++ b/ivy/func_wrapper.py @@ -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): @@ -187,11 +137,12 @@ def cross_caster(intersect): dtype = "" valid_float = sorted(ivy.valid_float_dtypes) valid_int = sorted(ivy.valid_int_dtypes) + valid_bool = [ivy.bool] intersect = sorted(intersect) if set(valid_int).issubset(intersect): # make dtype equal to default float dtype = ivy.default_float_dtype() - elif set(valid_float).issubset(intersect): + elif set(valid_float).issubset(intersect) or set(valid_bool).issubset(intersect): # make dtype equal to default int dtype = ivy.default_int_dtype() @@ -224,7 +175,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 +228,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 +268,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 +379,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 +418,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 +484,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 +496,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 +525,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 +551,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 +561,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 +571,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 +591,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 +622,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 +665,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 +689,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 +726,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 +746,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 +780,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 +873,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 +916,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 +976,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 +1003,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 +1070,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 +1214,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 +1237,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 +1273,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 +1373,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 +1428,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 +1556,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 ---------- @@ -1694,14 +1659,16 @@ def __exit__(self, *exec): if globals_getter_func().get(item, None): if isinstance(globals_getter_func()[item], FunctionType): # we need to add the decorator - globals_getter_func([ - item, - ( - _dtype_device_wrapper_creator("unsupported_dtypes", tuple)( - *self.args, **self.kwargs - ) - )(globals_getter_func()[item]), - ]) + globals_getter_func( + [ + item, + ( + _dtype_device_wrapper_creator( + "unsupported_dtypes", tuple + )(*self.args, **self.kwargs) + )(globals_getter_func()[item]), + ] + ) class with_supported_dtypes(contextlib.ContextDecorator): @@ -1728,14 +1695,16 @@ def __exit__(self, *exec): if globals_getter_func().get(item, None): if isinstance(globals_getter_func()[item], FunctionType): # we need to add the decorator - globals_getter_func([ - item, - ( - _dtype_device_wrapper_creator("supported_dtypes", tuple)( - *self.args, **self.kwargs - ) - )(globals_getter_func()[item]), - ]) + globals_getter_func( + [ + item, + ( + _dtype_device_wrapper_creator( + "supported_dtypes", tuple + )(*self.args, **self.kwargs) + )(globals_getter_func()[item]), + ] + ) class with_unsupported_devices(contextlib.ContextDecorator): @@ -1762,14 +1731,16 @@ def __exit__(self, *exec): if globals_getter_func().get(item, None): if isinstance(globals_getter_func()[item], FunctionType): # we need to add the decorator - globals_getter_func([ - item, - ( - _dtype_device_wrapper_creator("unsupported_devices", tuple)( - *self.args, **self.kwargs - ) - )(globals_getter_func()[item]), - ]) + globals_getter_func( + [ + item, + ( + _dtype_device_wrapper_creator( + "unsupported_devices", tuple + )(*self.args, **self.kwargs) + )(globals_getter_func()[item]), + ] + ) class with_supported_devices(contextlib.ContextDecorator): @@ -1796,14 +1767,16 @@ def __exit__(self, *exec): if globals_getter_func().get(item, None): if isinstance(globals_getter_func()[item], FunctionType): # we need to add the decorator - globals_getter_func([ - item, - ( - _dtype_device_wrapper_creator("supported_devices", tuple)( - *self.args, **self.kwargs - ) - )(globals_getter_func()[item]), - ]) + globals_getter_func( + [ + item, + ( + _dtype_device_wrapper_creator( + "supported_devices", tuple + )(*self.args, **self.kwargs) + )(globals_getter_func()[item]), + ] + ) class with_unsupported_device_and_dtypes(contextlib.ContextDecorator): @@ -1852,14 +1825,16 @@ def __exit__(self, *exec): if globals_getter_func().get(item, None): if isinstance(globals_getter_func()[item], FunctionType): # we need to add the decorator - globals_getter_func([ - item, - ( - _dtype_device_wrapper_creator( - "unsupported_device_and_dtype", tuple - )(*self.args, **self.kwargs) - )(globals_getter_func()[item]), - ]) + globals_getter_func( + [ + item, + ( + _dtype_device_wrapper_creator( + "unsupported_device_and_dtype", tuple + )(*self.args, **self.kwargs) + )(globals_getter_func()[item]), + ] + ) class with_supported_device_and_dtypes(contextlib.ContextDecorator): @@ -1908,14 +1883,16 @@ def __exit__(self, *exec): if globals_getter_func().get(item, None): if isinstance(globals_getter_func()[item], FunctionType): # we need to add the decorator - globals_getter_func([ - item, - ( - _dtype_device_wrapper_creator( - "supported_device_and_dtype", tuple - )(*self.args, **self.kwargs) - )(globals_getter_func()[item]), - ]) + globals_getter_func( + [ + item, + ( + _dtype_device_wrapper_creator( + "supported_device_and_dtype", tuple + )(*self.args, **self.kwargs) + )(globals_getter_func()[item]), + ] + ) class override(contextlib.ContextDecorator): diff --git a/ivy/functional/backends/jax/__init__.py b/ivy/functional/backends/jax/__init__.py index ca2e47c668e58..d4396ae03b166 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 @@ -55,14 +56,10 @@ def _array_unflatten(aux_data, children): if version.parse(jax.__version__) >= version.parse("0.4.1"): JaxArray = jax.Array - NativeArray = (jax.Array,) + NativeArray = jax.Array else: JaxArray = jaxlib.xla_extension.DeviceArray - NativeArray = (jaxlib.xla_extension.DeviceArray,) - -if version.parse(jax.__version__) <= version.parse("0.4.8"): - JaxArray = Union[JaxArray, jax.interpreters.xla._DeviceArray] - NativeArray += (jax.interpreters.xla._DeviceArray,) + NativeArray = jaxlib.xla_extension.DeviceArray # noinspection PyUnresolvedReferences,PyProtectedMember NativeDevice = jaxlib.xla_extension.Device @@ -101,7 +98,7 @@ def _array_unflatten(aux_data, children): # update these to add new dtypes valid_dtypes = { - "0.4.20 and below": ( + "0.4.25 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -120,7 +117,7 @@ def _array_unflatten(aux_data, children): ) } valid_numeric_dtypes = { - "0.4.20 and below": ( + "0.4.25 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -139,7 +136,7 @@ def _array_unflatten(aux_data, children): } valid_int_dtypes = { - "0.4.20 and below": ( + "0.4.25 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -152,12 +149,12 @@ def _array_unflatten(aux_data, children): } valid_uint_dtypes = { - "0.4.20 and below": (ivy.uint8, ivy.uint16, ivy.uint32, ivy.uint64) + "0.4.25 and below": (ivy.uint8, ivy.uint16, ivy.uint32, ivy.uint64) } valid_float_dtypes = { - "0.4.20 and below": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64) + "0.4.25 and below": (ivy.bfloat16, ivy.float16, ivy.float32, ivy.float64) } -valid_complex_dtypes = {"0.4.20 and below": (ivy.complex64, ivy.complex128)} +valid_complex_dtypes = {"0.4.25 and below": (ivy.complex64, ivy.complex128)} # leave these untouched @@ -172,12 +169,12 @@ def _array_unflatten(aux_data, children): # invalid data types # update these to add new dtypes -invalid_dtypes = {"0.4.20 and below": ()} -invalid_numeric_dtypes = {"0.4.20 and below": ()} -invalid_int_dtypes = {"0.4.20 and below": ()} -invalid_float_dtypes = {"0.4.20 and below": ()} -invalid_uint_dtypes = {"0.4.20 and below": ()} -invalid_complex_dtypes = {"0.4.20 and below": ()} +invalid_dtypes = {"0.4.25 and below": ()} +invalid_numeric_dtypes = {"0.4.25 and below": ()} +invalid_int_dtypes = {"0.4.25 and below": ()} +invalid_float_dtypes = {"0.4.25 and below": ()} +invalid_uint_dtypes = {"0.4.25 and below": ()} +invalid_complex_dtypes = {"0.4.25 and below": ()} # leave these untouched invalid_dtypes = _dtype_from_version(invalid_dtypes, backend_version) @@ -240,8 +237,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/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 e12164e617440..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 diff --git a/ivy/functional/backends/jax/elementwise.py b/ivy/functional/backends/jax/elementwise.py index 23e3211ccffb5..abca167e89aa5 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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], @@ -511,9 +516,12 @@ def trapz( axis: int = -1, out: Optional[JaxArray] = None, ) -> JaxArray: - return jnp.trapz(y, x=x, dx=dx, axis=axis) + return jnp.trapezoid(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.20 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.20 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.20 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 f2e298cf4400c..f8a87fc7607f1 100644 --- a/ivy/functional/backends/jax/experimental/activations.py +++ b/ivy/functional/backends/jax/experimental/activations.py @@ -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: @@ -159,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/elementwise.py b/ivy/functional/backends/jax/experimental/elementwise.py index 4a005bd28c203..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.20 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) @@ -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 95fbb1277a19c..335b0745e2ce2 100644 --- a/ivy/functional/backends/jax/experimental/layers.py +++ b/ivy/functional/backends/jax/experimental/layers.py @@ -440,7 +440,7 @@ def avg_pool3d( return res -@with_supported_dtypes({"0.4.20 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"0.4.24 and below": ("float32", "float64")}, backend_version) def dct( x: JaxArray, /, @@ -822,7 +822,7 @@ def ifftn( @with_unsupported_dtypes( - {"0.4.20 and below": ("bfloat16", "float16", "complex")}, backend_version + {"0.4.24 and below": ("bfloat16", "float16", "complex")}, backend_version ) def embedding( weights: JaxArray, @@ -870,7 +870,7 @@ def rfft( return ret -@with_unsupported_dtypes({"0.4.20 and below": ("float16", "complex")}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("float16", "complex")}, backend_version) def rfftn( x: JaxArray, s: Optional[Sequence[int]] = None, 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 1eb7c5ac75315..59ee341ab7870 100644 --- a/ivy/functional/backends/jax/experimental/manipulation.py +++ b/ivy/functional/backends/jax/experimental/manipulation.py @@ -15,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 @@ -442,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) @@ -462,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 0afa2f35dc9a1..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.20 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 232bf3d4be6e2..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.20 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 65beaf0363722..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.20 and below": ("bfloat16",)}, + {"0.4.24 and below": ("bfloat16",)}, backend_version, ) def histogram( @@ -121,7 +121,7 @@ def histogram( @with_unsupported_dtypes( - {"0.4.20 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.20 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 c2f643afcd9cc..6199d7585877f 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( @@ -68,13 +69,15 @@ def get_item( *, 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.20 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 @@ -271,7 +280,7 @@ def inplace_update( val_native.flatten() ) - base.data = base_flat.reshape(base.shape) + base.data = jnp.reshape(base_flat, base.shape) for ref in base._view_refs: view = ref() @@ -420,7 +429,7 @@ def vmap( ) -@with_unsupported_dtypes({"0.4.20 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 001de4a03d0ff..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 @@ -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: @@ -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": @@ -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 0e622f58b8bed..d7b5c55cc9d9a 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.20 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.20 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.20 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.20 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.20 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("complex",)}, backend_version) def diagonal( x: JaxArray, /, @@ -104,7 +104,7 @@ def tensorsolve( @with_unsupported_dtypes( - {"0.4.20 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.20 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.20 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.20 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.20 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.20 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).to_native() 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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 161ba13f9f082..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.20 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..44163895c8533 --- /dev/null +++ b/ivy/functional/backends/jax/module.py @@ -0,0 +1,1156 @@ +# global +from __future__ import annotations +import re +import jax +from flax import linen as nn +import jax.tree_util as tree +import jax.numpy as jnp +import functools +from typing import NamedTuple, Callable, Any, Tuple, List, Dict, Type +import inspect +from collections import OrderedDict + + +def get_assignment_dict(): + # Traverse the call stack + lhs = None + for frame_info in inspect.stack(): + # Check if the code context is an assignment statement + if frame_info.code_context and "=" in frame_info.code_context[0]: + # Split the assignment and retrieve the LHS + lhs = frame_info.code_context[0].split("=")[0].strip() + if "self" not in lhs: + continue + break + + if not lhs: + return None, "" + + # Replace indexing with attribute access + lhs = re.sub(r"\[(\d+)\]", r".\1", lhs) + + # Split the LHS based on "." and get individual components + components = lhs.split(".") + + # Initialize the dictionary + assignment_dict = {} + + # Retrieve the live objects associated with each component + for i in range(len(components)): + # Construct the key + key = ".".join(components[: i + 1]) + + # Retrieve the value + if i == 0: + value = frame_info.frame.f_locals.get(components[i]) + else: + value = getattr(assignment_dict[".".join(components[:i])], components[i]) + + # Add the key-value pair to the dictionary + assignment_dict[key] = value + + return assignment_dict, lhs + + +def store_frame_info(fn): + @functools.wraps(fn) + def frame_info_wrapper(self, *args, **kwargs): + if self._previous_frame_info is None: + # store the info about the calling frame. + stack = inspect.stack() + self._previous_frame_info = stack[1] + res = fn(self, *args, **kwargs) + # reset the frame-info + self._previous_frame_info = None + return res + + return frame_info_wrapper + + +# 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 + def _get_first_array(*args, **kwargs): + arr = None + flattened_args, _ = jax.tree.flatten((args, kwargs)) + arr_candidates = jax.tree.map( + lambda x: x if isinstance(x, (jax.Array)) else False, + flattened_args, + ) + for arr_candidate in arr_candidates: + if arr_candidate is not False: + arr = arr_candidate + break + return arr + + @staticmethod + def _get_input_shapes(*args): + input_shapes = [] + for x in args: + if isinstance(x, (jax.Array)): + input_shapes.append(x.shape) + else: + try: + x = jnp.asarray(x) + input_shapes.append(x.shape) + except Exception: + input_shapes.append(None) + return input_shapes + + @staticmethod + 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 + def _remove_duplicate_variables(vs, created, /): + created_ids = jax.tree.map(lambda x: id(x), created) + vs_ids = jax.tree.map(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 = tree.tree_map_with_path( + lambda kc, x: unique_callback(x, kc), created_ids + ) + vs_ids = tree.tree_map_with_path( + 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 + 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 + 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 + 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 + 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 + 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 Layer(nn.Module, 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 + _previous_frame_info = 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, + module_dict=None, + **kwargs, + ): + 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 = module_dict if module_dict is not None else 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 jax.float32 + if build_mode != "on_init": + return + self.build(*args, dynamic_backend=dynamic_backend, **kwargs) + + def build( + self, + *args, + from_call=False, + device=None, + dtype=None, + dynamic_backend=None, + **kwargs, + ): + self._built = True + return + + def register_buffer(self, name: str, value: jax.Array): + self._buffers.update({name: value}) + return value + + def register_parameter(self, name: str, value: jax.Array): + self._v.update({name: value}) + + def train(self, mode: bool = True): + self._training = mode + for module in self.children(): + if isinstance(module, nn.Module) and not hasattr(module, "train"): + module.trainable = mode + continue + module.train(mode) + self.trainable = mode + return self + + def eval(self): + return self.train(mode=False) + + def call(self, inputs, training=None, mask=None): + raise NotImplementedError( + "When subclassing the `Module` class, you should implement a `call` method." + ) + + def get_config(self): + base_config = super().get_config() + config = {} + + # Get the names and values of positional arguments in __init__ + init_signature = inspect.signature(self.__init__) + arg_names = list(init_signature.parameters.keys()) + + # Include the positional arguments in the config + var_positional_arg_encountered = False + var_positional_arg_name = None + offset = 0 + for i, arg in enumerate(self._args[1:]): + arg_name = arg_names[min(i, len(arg_names) - 1)] + if var_positional_arg_encountered: + config.update( + { + f"{var_positional_arg_name}_{i - offset}": arg, + } + ) + elif ( + init_signature.parameters[arg_name].kind + == inspect.Parameter.VAR_POSITIONAL + ): + var_positional_arg_encountered = True + var_positional_arg_name = arg_name + offset = i + config.update( + { + f"{var_positional_arg_name}_{0}": arg, + } + ) + else: + config.update( + { + arg_name: arg, + } + ) + + # Include the keywords arguments in the config + kwargs = self._kwargs.copy() + kwargs.pop("devices", None) + config.update(**kwargs) + return {**base_config, **config} + + @classmethod + def from_config(cls, config): + # Get the signature of the __init__ method + init_signature = inspect.signature(cls.__init__) + arg_names = list(init_signature.parameters.keys()) + + # Separate positional and keyword arguments based on the __init__ signature + args = [] + pos_or_kw = OrderedDict() + kwargs = {} + var_positional_args = [] + for arg_name in arg_names: + if ( + arg_name in config + and init_signature.parameters[arg_name].kind + == inspect.Parameter.KEYWORD_ONLY + ): + # Handle keyword arguments + kwargs[arg_name] = config.pop(arg_name) + elif ( + arg_name in config + and init_signature.parameters[arg_name].kind + == inspect.Parameter.POSITIONAL_OR_KEYWORD + ): + # Handle positional or keyword arguments + pos_or_kw[arg_name] = config.pop(arg_name) + elif any(re.match(rf"{arg_name}_\d+", key) for key in config.keys()): + # Handle variable positional arguments + var_positional_args.extend( + [ + config.pop(key) + for key in sorted(config.keys()) + if re.match(rf"{arg_name}_\d+", key) + ] + ) + + # Unpack positional arguments and the rest as keyword arguments + config.pop("name", None) + config.pop("trainable", None) + config.pop("dtype", None) + kwargs.update(config) + + # Determine the final args and kwargs + if var_positional_args: + args = list(pos_or_kw.values()) + var_positional_args + else: + kwargs.update(pos_or_kw) + + return cls(*args, **kwargs) + + # Methods to be Optionally Overridden # + # -----------------------------------# + + def _create_variables(self, *, device=None, dtype=None): + return {} + + def _build(self, *args, **kwargs) -> bool: + return True + + def _forward(self, *args, **kwargs): + raise NotImplementedError( + "When subclassing the `Module` class, you should " + "implement a `_forward` method." + ) + + 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 # + # ---------------# + @store_frame_info + 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 + + 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) + + def __setattr__(self, name, value): + if name in ["v", "buffers"]: + name = "_" + name + if isinstance(value, (Layer, nn.Module)): + _dict = getattr(self, "__dict__", None) + if _dict: + _dict[name] = value + + # compute the module dict + self._compute_module_dict() + + obj_to_search = ( + None + if not isinstance(value, (Layer, nn.Module)) + else ( + self._modules + if hasattr(self, "_modules") and self._modules + else self + ) + ) + found_vars = self._find_variables( + obj=obj_to_search, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + ) + flattened_v, v_spec = tree_flatten(found_vars) + flattend_kc = v_spec.get_keychains() + for kc, v in zip(flattend_kc, flattened_v): + new_kc = kc.replace("/", ".") + if new_kc not in self.v: + self.register_parameter(new_kc, v) + + # once all variables built, find and assign buffers + found_buffers = self._find_variables( + obj=obj_to_search, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + trainable=False, + ) + flattened_buf, buf_spec = tree_flatten(found_buffers) + flattend_kc = buf_spec.get_keychains() + for kc, buf in zip(flattend_kc, flattened_buf): + new_kc = kc.replace("/", ".") + self.register_buffer(new_kc, buf) + + super().__setattr__(name, value) + return + else: + try: + obj_to_search = getattr(self, name) + except AttributeError: + obj_to_search = None + if isinstance(obj_to_search, Layer): + # retrieve all hierarchical submodules + assign_dict, kc = get_assignment_dict() + + # Iterate over all submods in assign_dict + # updating their `v` and `buffers` with the + # new value + for key, submod in assign_dict.items(): + # Get the subkey to match + subkey = kc[len(key) :].lstrip(".") + + if hasattr(submod, "v"): + for v_key, v_value in submod.v.items(): + if v_key.startswith(subkey): + submod.register_parameter(v_key, value) + + # Repeat the same process for submod.buffers + if hasattr(submod, "buffers"): + for b_key, b_value in submod.buffers.items(): + if b_key.startswith(subkey): + submod.register_buffer(b_key, value) + + # finally update the module dict + self._module_dict[name] = value + + return super().__setattr__(name, value) + + def __delattr__(self, name): + if hasattr(self, name): + if isinstance(getattr(self, name), (Layer, nn.Module)): + super().__delattr__(name) + 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), Layer): + 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 + + +class Model(nn.Module, 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 + _previous_frame_info = None + + def setup( + 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, + module_dict=None, + **kwargs, + ): + 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 = module_dict if module_dict is not None else 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 jax.float32 + if build_mode != "on_init": + return + self.build(*args, dynamic_backend=dynamic_backend, **kwargs) + + def build( + self, + *args, + from_call=False, + device=None, + dtype=None, + dynamic_backend=None, + **kwargs, + ): + self._built = True + return + + def register_buffer(self, name: str, value: jax.Array): + self._buffers.update({name: value}) + return value + + def register_parameter(self, name: str, value: jax.Array): + self._v.update({name: value}) + + def train(self, mode: bool = True): + self._training = mode + for module in self.children(): + if isinstance(module, nn.Module) and not hasattr(module, "train"): + module.trainable = mode + continue + module.train(mode) + self.trainable = mode + return self + + def eval(self): + return self.train(mode=False) + + def call(self, inputs, training=None, mask=None): + raise NotImplementedError( + "When subclassing the `Module` class, you should implement a `call` method." + ) + + def get_config(self): + base_config = super().get_config() + config = {} + + # Get the names and values of positional arguments in __init__ + init_signature = inspect.signature(self.__init__) + arg_names = list(init_signature.parameters.keys()) + + # Include the positional arguments in the config + var_positional_arg_encountered = False + var_positional_arg_name = None + offset = 0 + for i, arg in enumerate(self._args[1:]): + arg_name = arg_names[min(i, len(arg_names) - 1)] + if var_positional_arg_encountered: + config.update( + { + f"{var_positional_arg_name}_{i - offset}": arg, + } + ) + elif ( + init_signature.parameters[arg_name].kind + == inspect.Parameter.VAR_POSITIONAL + ): + var_positional_arg_encountered = True + var_positional_arg_name = arg_name + offset = i + config.update( + { + f"{var_positional_arg_name}_{0}": arg, + } + ) + else: + config.update( + { + arg_name: arg, + } + ) + + # Include the keywords arguments in the config + kwargs = self._kwargs.copy() + kwargs.pop("devices", None) + config.update(**kwargs) + return {**base_config, **config} + + @classmethod + def from_config(cls, config): + # Get the signature of the __init__ method + init_signature = inspect.signature(cls.__init__) + arg_names = list(init_signature.parameters.keys()) + + # Separate positional and keyword arguments based on the __init__ signature + args = [] + pos_or_kw = OrderedDict() + kwargs = {} + var_positional_args = [] + for arg_name in arg_names: + if ( + arg_name in config + and init_signature.parameters[arg_name].kind + == inspect.Parameter.KEYWORD_ONLY + ): + # Handle keyword arguments + kwargs[arg_name] = config.pop(arg_name) + elif ( + arg_name in config + and init_signature.parameters[arg_name].kind + == inspect.Parameter.POSITIONAL_OR_KEYWORD + ): + # Handle positional or keyword arguments + pos_or_kw[arg_name] = config.pop(arg_name) + elif any(re.match(rf"{arg_name}_\d+", key) for key in config.keys()): + # Handle variable positional arguments + var_positional_args.extend( + [ + config.pop(key) + for key in sorted(config.keys()) + if re.match(rf"{arg_name}_\d+", key) + ] + ) + + # Unpack positional arguments and the rest as keyword arguments + config.pop("name", None) + config.pop("trainable", None) + config.pop("dtype", None) + kwargs.update(config) + + # Determine the final args and kwargs + if var_positional_args: + args = list(pos_or_kw.values()) + var_positional_args + else: + kwargs.update(pos_or_kw) + + return cls(*args, **kwargs) + + # Methods to be Optionally Overridden # + # -----------------------------------# + + def _create_variables(self, *, device=None, dtype=None): + return {} + + def _build(self, *args, **kwargs) -> bool: + return True + + def _forward(self, *args, **kwargs): + raise NotImplementedError( + "When subclassing the `Module` class, you should " + "implement a `_forward` method." + ) + + 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 # + # ---------------# + @store_frame_info + def __call__( + self, + *args, + v=None, + buffers=None, + **kwargs, + ): + ret = self._call(*args, v=v, buffers=buffers, **kwargs) + return ret + + 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) + + def __setattr__(self, name, value): + if name in ["v", "buffers"]: + name = "_" + name + if isinstance(value, (Layer, Model, nn.Module)): + _dict = getattr(self, "__dict__", None) + if _dict: + _dict[name] = value + + # compute the module dict + self._compute_module_dict() + + obj_to_search = ( + None + if not isinstance(value, (nn.Module, Layer, Model)) + else ( + self._modules + if hasattr(self, "_modules") and self._modules + else self + ) + ) + found_vars = self._find_variables( + obj=obj_to_search, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + ) + flattened_v, v_spec = tree_flatten(found_vars) + flattend_kc = v_spec.get_keychains() + for kc, v in zip(flattend_kc, flattened_v): + new_kc = kc.replace("/", ".") + if new_kc not in self.v: + self.register_parameter(new_kc, v) + + # once all variables built, find and assign buffers + found_buffers = self._find_variables( + obj=obj_to_search, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + trainable=False, + ) + flattened_buf, buf_spec = tree_flatten(found_buffers) + flattend_kc = buf_spec.get_keychains() + for kc, buf in zip(flattend_kc, flattened_buf): + new_kc = kc.replace("/", ".") + self.register_buffer(new_kc, buf) + + super().__setattr__(name, value) + return + else: + try: + obj_to_search = getattr(self, name) + except AttributeError: + obj_to_search = None + if isinstance(obj_to_search, (Model, Layer)): + # retrieve all hierarchical submodules + assign_dict, kc = get_assignment_dict() + + # Iterate over all submods in assign_dict + # updating their `v` and `buffers` with the + # new value + for key, submod in assign_dict.items(): + # Get the subkey to match + subkey = kc[len(key) :].lstrip(".") + + if hasattr(submod, "v"): + for v_key, v_value in submod.v.items(): + if v_key.startswith(subkey): + submod.register_parameter(v_key, value) + + # Repeat the same process for submod.buffers + if hasattr(submod, "buffers"): + for b_key, b_value in submod.buffers.items(): + if b_key.startswith(subkey): + submod.register_buffer(b_key, value) + + # finally update the module dict + self._module_dict[name] = value + + return super().__setattr__(name, value) + + def __delattr__(self, name): + if hasattr(self, name): + if isinstance( + getattr(self, name), + (Layer, Model, nn.Module), + ): + super().__delattr__(name) + 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), (Layer, 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/jax/random.py b/ivy/functional/backends/jax/random.py index 506eb095fae5c..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.20 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 679c02981e49e..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.20 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.20 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 1dc7eecb5b2c4..27ea0596a1e2e 100644 --- a/ivy/functional/backends/jax/sorting.py +++ b/ivy/functional/backends/jax/sorting.py @@ -18,12 +18,7 @@ def argsort( stable: bool = True, out: Optional[JaxArray] = None, ) -> JaxArray: - kind = "stable" if stable else "quicksort" - return ( - jnp.argsort(-x, axis=axis, kind=kind) - if descending - else jnp.argsort(x, axis=axis, kind=kind) - ) + return jnp.argsort(x, axis=axis, stable=stable, descending=descending) def sort( @@ -56,9 +51,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 +73,7 @@ def searchsorted( # msort -@with_unsupported_dtypes({"0.4.20 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 9e0cef560e067..8f1a9b8b4a17f 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( @@ -38,18 +42,22 @@ def max( @with_unsupported_dtypes( - {"0.4.20 and below": "bfloat16"}, + {"0.4.24 and below": "bfloat16"}, backend_version, ) def mean( x: JaxArray, /, - *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + *, + dtype: Optional[jnp.dtype] = None, out: Optional[JaxArray] = None, ) -> JaxArray: axis = tuple(axis) if isinstance(axis, list) else axis + if dtype is not None: + dtype = ivy.as_native_dtype(dtype) + x = x.astype(dtype) return jnp.mean(x, axis=axis, keepdims=keepdims, dtype=x.dtype) @@ -143,7 +151,7 @@ def var( # ------# -@with_unsupported_dtypes({"0.4.20 and below": "bfloat16"}, backend_version) +@with_unsupported_dtypes({"0.4.24 and below": ("bfloat16", "bool")}, backend_version) def cumprod( x: JaxArray, /, @@ -179,6 +187,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/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/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/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 0939aa145f73c..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: - 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.2 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.2 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.2 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.2 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.2 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.2 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.2 and below": (ivy.bfloat16,)} -invalid_numeric_dtypes = {"1.26.2 and below": (ivy.bfloat16,)} -invalid_int_dtypes = {"1.26.2 and below": ()} -invalid_float_dtypes = {"1.26.2 and below": (ivy.bfloat16,)} -invalid_uint_dtypes = {"1.26.2 and below": ()} -invalid_complex_dtypes = {"1.26.2 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/data_type.py b/ivy/functional/backends/numpy/data_type.py index a748843b6513e..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.2 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.2 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 d636feb8d8f25..b173e50154f92 100644 --- a/ivy/functional/backends/numpy/device.py +++ b/ivy/functional/backends/numpy/device.py @@ -1,4 +1,5 @@ -"""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 diff --git a/ivy/functional/backends/numpy/elementwise.py b/ivy/functional/backends/numpy/elementwise.py index 0d0c6e8ce9022..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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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 e48bbedb99b28..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.2 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 @@ -202,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 97d6325605a41..8add9faa6c67e 100644 --- a/ivy/functional/backends/numpy/experimental/creation.py +++ b/ivy/functional/backends/numpy/experimental/creation.py @@ -98,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) diff --git a/ivy/functional/backends/numpy/experimental/elementwise.py b/ivy/functional/backends/numpy/experimental/elementwise.py index d81989479ff5c..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.2 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) @@ -338,16 +338,18 @@ def modf( # ---digamma---# kLanczosGamma = 7 # aka g kBaseLanczosCoeff = 0.99999999999980993227684700473478 -kLanczosCoefficients = np.array([ - 676.520368121885098567009190444019, - -1259.13921672240287047156078755283, - 771.3234287776530788486528258894, - -176.61502916214059906584551354, - 12.507343278686904814458936853, - -0.13857109526572011689554707, - 9.984369578019570859563e-6, - 1.50563273514931155834e-7, -]) +kLanczosCoefficients = np.array( + [ + 676.520368121885098567009190444019, + -1259.13921672240287047156078755283, + 771.3234287776530788486528258894, + -176.61502916214059906584551354, + 12.507343278686904814458936853, + -0.13857109526572011689554707, + 9.984369578019570859563e-6, + 1.50563273514931155834e-7, + ] +) def digamma( @@ -397,42 +399,47 @@ def digamma( # --- LGAMMA --- # LANCZOS_N = 13 lanczos_g = 6.024680040776729583740234375 -lanczos_num_coeffs = np.array([ - 23531376880.410759688572007674451636754734846804940, - 42919803642.649098768957899047001988850926355848959, - 35711959237.355668049440185451547166705960488635843, - 17921034426.037209699919755754458931112671403265390, - 6039542586.3520280050642916443072979210699388420708, - 1439720407.3117216736632230727949123939715485786772, - 248874557.86205415651146038641322942321632125127801, - 31426415.585400194380614231628318205362874684987640, - 2876370.6289353724412254090516208496135991145378768, - 186056.26539522349504029498971604569928220784236328, - 8071.6720023658162106380029022722506138218516325024, - 210.82427775157934587250973392071336271166969580291, - 2.5066282746310002701649081771338373386264310793408, -]) -lanczos_den_coeffs = np.array([ - 0.0, - 39916800.0, - 120543840.0, - 150917976.0, - 105258076.0, - 45995730.0, - 13339535.0, - 2637558.0, - 357423.0, - 32670.0, - 1925.0, - 66.0, - 1.0, -]) +lanczos_num_coeffs = np.array( + [ + 23531376880.410759688572007674451636754734846804940, + 42919803642.649098768957899047001988850926355848959, + 35711959237.355668049440185451547166705960488635843, + 17921034426.037209699919755754458931112671403265390, + 6039542586.3520280050642916443072979210699388420708, + 1439720407.3117216736632230727949123939715485786772, + 248874557.86205415651146038641322942321632125127801, + 31426415.585400194380614231628318205362874684987640, + 2876370.6289353724412254090516208496135991145378768, + 186056.26539522349504029498971604569928220784236328, + 8071.6720023658162106380029022722506138218516325024, + 210.82427775157934587250973392071336271166969580291, + 2.5066282746310002701649081771338373386264310793408, + ] +) +lanczos_den_coeffs = np.array( + [ + 0.0, + 39916800.0, + 120543840.0, + 150917976.0, + 105258076.0, + 45995730.0, + 13339535.0, + 2637558.0, + 357423.0, + 32670.0, + 1925.0, + 66.0, + 1.0, + ] +) def sinpi(x): y = np.abs(x) % 2.0 n = np.round(2.0 * y) - assert n >= 0 and n <= 4 + assert n >= 0 + assert n <= 4 if n == 0: r = np.sin(np.pi * y) @@ -511,45 +518,53 @@ def func(x): # --- erfc --- # # Polynomials for computing erf/erfc. Originally from cephes library. # https://netlib.org/cephes/doubldoc.html -kErfcPCoefficient = np.array([ - 2.46196981473530512524e-10, - 5.64189564831068821977e-1, - 7.46321056442269912687e0, - 4.86371970985681366614e1, - 1.96520832956077098242e2, - 5.26445194995477358631e2, - 9.34528527171957607540e2, - 1.02755188689515710272e3, - 5.57535335369399327526e2, -]) -kErfcQCoefficient = np.array([ - 1.00000000000000000000e0, - 1.32281951154744992508e1, - 8.67072140885989742329e1, - 3.54937778887819891062e2, - 9.75708501743205489753e2, - 1.82390916687909736289e3, - 2.24633760818710981792e3, - 1.65666309194161350182e3, - 5.57535340817727675546e2, -]) -kErfcRCoefficient = np.array([ - 5.64189583547755073984e-1, - 1.27536670759978104416e0, - 5.01905042251180477414e0, - 6.16021097993053585195e0, - 7.40974269950448939160e0, - 2.97886665372100240670e0, -]) -kErfcSCoefficient = np.array([ - 1.00000000000000000000e0, - 2.26052863220117276590e0, - 9.39603524938001434673e0, - 1.20489539808096656605e1, - 1.70814450747565897222e1, - 9.60896809063285878198e0, - 3.36907645100081516050e0, -]) +kErfcPCoefficient = np.array( + [ + 2.46196981473530512524e-10, + 5.64189564831068821977e-1, + 7.46321056442269912687e0, + 4.86371970985681366614e1, + 1.96520832956077098242e2, + 5.26445194995477358631e2, + 9.34528527171957607540e2, + 1.02755188689515710272e3, + 5.57535335369399327526e2, + ] +) +kErfcQCoefficient = np.array( + [ + 1.00000000000000000000e0, + 1.32281951154744992508e1, + 8.67072140885989742329e1, + 3.54937778887819891062e2, + 9.75708501743205489753e2, + 1.82390916687909736289e3, + 2.24633760818710981792e3, + 1.65666309194161350182e3, + 5.57535340817727675546e2, + ] +) +kErfcRCoefficient = np.array( + [ + 5.64189583547755073984e-1, + 1.27536670759978104416e0, + 5.01905042251180477414e0, + 6.16021097993053585195e0, + 7.40974269950448939160e0, + 2.97886665372100240670e0, + ] +) +kErfcSCoefficient = np.array( + [ + 1.00000000000000000000e0, + 2.26052863220117276590e0, + 9.39603524938001434673e0, + 1.20489539808096656605e1, + 1.70814450747565897222e1, + 9.60896809063285878198e0, + 3.36907645100081516050e0, + ] +) # Evaluate the polynomial given coefficients and `x`. @@ -570,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 @@ -601,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 2077d276631c9..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.2 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 8672a0d49f587..8e8344a78d166 100644 --- a/ivy/functional/backends/numpy/experimental/layers.py +++ b/ivy/functional/backends/numpy/experimental/layers.py @@ -729,7 +729,7 @@ def fft( return np.fft.fft(x, n, dim, norm).astype(out_dtype) -@with_supported_dtypes({"1.26.2 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"1.26.3 and below": ("float32", "float64")}, backend_version) def dct( x: np.ndarray, /, @@ -994,7 +994,7 @@ def ifftn( return np.fft.ifftn(x, s, axes, norm).astype(x.dtype) -@with_unsupported_dtypes({"1.26.2 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("complex",)}, backend_version) def embedding( weights: np.ndarray, indices: np.ndarray, diff --git a/ivy/functional/backends/numpy/experimental/linear_algebra.py b/ivy/functional/backends/numpy/experimental/linear_algebra.py index 1fc7eb964c89e..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.2 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.2 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.2 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 9da5beb3a95f8..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.2 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.2 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.2 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 9a86855d16ec6..dcc956b149d44 100644 --- a/ivy/functional/backends/numpy/experimental/manipulation.py +++ b/ivy/functional/backends/numpy/experimental/manipulation.py @@ -18,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 @@ -402,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] @@ -591,10 +594,28 @@ def put_along_axis( mode: Literal["sum", "min", "max", "mul", "replace"] = "replace", out: Optional[np.ndarray] = None, ): - ret = np.put_along_axis(arr.copy(), indices, values, axis) + ret = arr.copy() + values = np.asarray(values) + np.put_along_axis(ret, indices, values, axis) return ivy.inplace_update(out, ret) if ivy.exists(out) else ret 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 a8f2ec9b6a8a3..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.2 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 f49b9c9c3a8fd..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.2 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 a69b2a58bd10e..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.2 and below": ("bfloat16",)}, + {"1.26.3 and below": ("bfloat16",)}, backend_version, ) def histogram( @@ -534,7 +534,7 @@ def __get_index(lst, indices=None, prefix=None): return indices -@with_unsupported_dtypes({"1.26.2 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 1b80e19a657cf..e185ef08998c8 100644 --- a/ivy/functional/backends/numpy/general.py +++ b/ivy/functional/backends/numpy/general.py @@ -1,19 +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.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: @@ -36,6 +40,8 @@ def get_item( *, copy: Optional[bool] = None, ) -> np.ndarray: + if copy: + x = x.copy() return x.__getitem__(query) @@ -46,7 +52,7 @@ def set_item( val: np.ndarray, /, *, - copy: Optional[bool] = False, + copy: bool = False, ) -> np.ndarray: if copy: x = np.copy(x) @@ -168,6 +174,10 @@ 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 @@ -434,7 +444,7 @@ def _vmap(*args): return _vmap -@with_unsupported_dtypes({"1.26.2 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 d5fe77211f752..20424a1da7ec5 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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).to_native() 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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 0f59794f34ad9..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.2 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 203e283b1009f..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 @@ -51,7 +52,7 @@ def random_normal( return np.asarray(np.random.normal(mean, std, shape), dtype=dtype) -@with_unsupported_dtypes({"1.26.2 and below": ("bfloat16",)}, backend_version) +@with_unsupported_dtypes({"1.26.3 and below": ("bfloat16",)}, backend_version) def multinomial( population_size: int, num_samples: int, @@ -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 a79ffbd715153..78fb8f5d6c925 100644 --- a/ivy/functional/backends/numpy/sorting.py +++ b/ivy/functional/backends/numpy/sorting.py @@ -42,7 +42,7 @@ def sort( # msort -@with_unsupported_dtypes({"1.26.2 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 e2028c726d2b5..2f6dbfa7380c2 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 @@ -48,11 +57,14 @@ def max( def mean( x: np.ndarray, /, - *, axis: Optional[Union[int, Sequence[int]]] = None, 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).to_native() axis = tuple(axis) if isinstance(axis, list) else axis return np.mean(x, axis=axis, keepdims=keepdims, dtype=x.dtype, out=out) @@ -169,7 +181,7 @@ def var( # ------# -@with_unsupported_dtypes({"1.26.2 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 86deeb0c9b9d6..0e5f0fa31e9ee 100644 --- a/ivy/functional/backends/paddle/__init__.py +++ b/ivy/functional/backends/paddle/__init__.py @@ -175,7 +175,7 @@ def rep_method(*args, **kwargs): ), } valid_int_dtypes = { - "2.5.2 and below": ( + "2.6.0 and below": ( ivy.int8, ivy.int16, ivy.int32, @@ -187,8 +187,8 @@ def rep_method(*args, **kwargs): "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.2 and below": (ivy.uint8,)} -valid_complex_dtypes = {"2.5.2 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) @@ -228,10 +228,10 @@ def rep_method(*args, **kwargs): ), } -invalid_int_dtypes = {"2.5.2 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} +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.5.2 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_complex_dtypes = {"2.5.2 and below": ()} +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 8182b0ef2263a..8dace1e706230 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. @@ -17,23 +16,32 @@ 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 @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex")}, + { + "2.6.0 and below": ( + "float32", + "float64", + "complex64", + ) + }, backend_version, ) -def relu(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: +def relu( + x: paddle.Tensor, /, *, complex_mode="jax", out: Optional[paddle.Tensor] = None +) -> paddle.Tensor: if paddle.is_complex(x): return paddle.complex(F.relu(x.real()), F.relu(x.imag())) return F.relu(x) @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def leaky_relu( @@ -53,7 +61,7 @@ def leaky_relu( @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def gelu( @@ -77,7 +85,7 @@ def gelu( @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def sigmoid( @@ -88,8 +96,8 @@ def sigmoid( return F.sigmoid(x) -@with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("bfloat16", "float16")}}, backend_version +@with_unsupported_dtypes( + {"2.6.0 and below": ("bfloat16", "float16", "complex128")}, backend_version ) def softmax( x: paddle.Tensor, @@ -109,6 +117,19 @@ def softmax( return paddle.divide(exp_x, paddle.sum(exp_x, axis=axis, keepdim=True)) +@with_supported_dtypes( + { + "2.6.0 and below": ( + "int32", + "int64", + "float64", + "complex128", + "float32", + "complex64", + ) + }, + backend_version, +) def softplus( x: paddle.Tensor, /, @@ -139,7 +160,7 @@ def softplus( # Softsign @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float16", "bfloat16")}}, backend_version + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version ) def softsign( x: paddle.Tensor, @@ -153,7 +174,7 @@ def softsign( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float16", "bfloat16")}}, backend_version + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version ) def log_softmax( x: paddle.Tensor, @@ -172,7 +193,7 @@ def log_softmax( @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def mish( @@ -188,7 +209,7 @@ def mish( @with_unsupported_device_and_dtypes( - {"2.5.2 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 e91fcc479ba5d..eff45e450d069 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, @@ -142,7 +143,7 @@ def empty_like( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "uint8", "int8", @@ -151,6 +152,7 @@ def empty_like( "complex64", "complex128", "bool", + "bfloat16", ) } }, @@ -214,6 +216,17 @@ def from_dlpack(x, /, *, out: Optional[paddle.Tensor] = None): 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], @@ -356,7 +369,7 @@ def _slice_at_axis(sl, axis): @with_unsupported_device_and_dtypes( - {"2.5.2 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], @@ -414,7 +427,7 @@ def linspace( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -471,6 +484,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, /, @@ -482,14 +511,18 @@ def ones_like( return paddle_backend.ones(shape=x.shape, dtype=dtype, device=device) -@with_unsupported_device_and_dtypes( +@with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( - "int8", - "int16", - "uint8", - "complex", + "int32", + "int64", + "float64", + "complex128", + "float16", + "float32", + "complex64", + "bool", ) } }, @@ -503,12 +536,13 @@ def tril( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", "uint8", "complex", + "bfloat16", ) } }, @@ -530,6 +564,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, /, @@ -551,7 +589,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: @@ -616,14 +654,14 @@ def one_hot( @with_unsupported_device_and_dtypes( - {"2.5.2 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": @@ -658,7 +696,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 2aca8cca43f87..aa009c9f7533c 100644 --- a/ivy/functional/backends/paddle/data_type.py +++ b/ivy/functional/backends/paddle/data_type.py @@ -118,6 +118,10 @@ def astype( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: dtype = ivy.as_native_dtype(dtype) + + if copy and 0 in x.shape: + return paddle.empty(x.shape, dtype=dtype) + if x.dtype == dtype: return x.clone() if copy else x return x.clone().cast(dtype) if copy else x.cast(dtype) @@ -143,7 +147,7 @@ def broadcast_arrays(*arrays: paddle.Tensor) -> List[paddle.Tensor]: @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", @@ -231,7 +235,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) @@ -274,7 +278,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 0270ccd9d1d5b..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 diff --git a/ivy/functional/backends/paddle/elementwise.py b/ivy/functional/backends/paddle/elementwise.py index 146d7e53ee102..76b60740ca9e7 100644 --- a/ivy/functional/backends/paddle/elementwise.py +++ b/ivy/functional/backends/paddle/elementwise.py @@ -1,15 +1,16 @@ # global -from typing import Union, Optional - import math +from typing import Optional, Union + import paddle -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_device_and_dtypes, with_supported_dtypes, + with_unsupported_device_and_dtypes, with_unsupported_dtypes, ) @@ -28,7 +29,7 @@ def _elementwise_helper(x1, x2): @with_unsupported_dtypes( - {"2.5.1 and below": ("int8", "uint8", "float16", "bool", "bfloat16")}, + {"2.6.0 and below": ("int8", "int16", "uint8", "float16", "bool", "bfloat16")}, backend_version, ) def add( @@ -59,7 +60,7 @@ def bitwise_xor( @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float16", "float32", "float64", @@ -79,7 +80,7 @@ def bitwise_invert( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -98,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, /, @@ -124,20 +129,15 @@ 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.5.1 and below": ("int8", "int16", "bfloat16", "unsigned", "float16")}, + {"2.6.0 and below": ("bool",)}, backend_version, ) def less_equal( @@ -148,11 +148,13 @@ def less_equal( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - 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) + 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) @@ -169,7 +171,7 @@ def bitwise_and( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex")}, + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version, ) def ceil(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -179,7 +181,7 @@ def ceil(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_dtypes( - {"2.5.1 and below": ("float16", "float32", "float64", "complex")}, + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version, ) def floor(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -190,7 +192,7 @@ def floor(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", @@ -205,8 +207,7 @@ def asin(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_dtypes( { - "2.5.2 and below": ( - "float16", + "2.6.0 and below": ( "float32", "float64", ) @@ -218,7 +219,7 @@ def asinh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float16", "float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float16", "float32", "float64", "complex")}}, backend_version, ) def sign( @@ -232,7 +233,7 @@ def sign( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex")}, backend_version + {"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.""" @@ -247,7 +248,7 @@ def sqrt(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", @@ -261,7 +262,7 @@ def cosh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex")}, backend_version + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version ) def log10(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: if paddle.is_complex(x): @@ -273,7 +274,7 @@ def log10(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex")}, + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version, ) def log2(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -286,7 +287,7 @@ def log2(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex")}, + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version, ) def log1p(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -297,7 +298,7 @@ def log1p(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float", "int32", "int64", @@ -314,7 +315,7 @@ def isnan(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle @with_unsupported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int8", "uint8", ) @@ -329,23 +330,17 @@ def less( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if paddle.is_complex(x1): - real = paddle.less_than(x1.real(), x2.real()) - imag = paddle.less_than(x1.imag(), x2.imag()) - return logical_and(real, imag) + 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, x2) -@with_unsupported_dtypes( - { - "2.5.1 and below": ( - "int8", - "int16", - "uint8", - "float16", - ) - }, +@with_supported_dtypes( + {"2.6.0 and below": ("bool", "int32", "int64", "float32", "float64", "complex")}, backend_version, ) def multiply( @@ -356,12 +351,20 @@ def multiply( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) + 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_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", @@ -374,19 +377,17 @@ def cos(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.T return paddle.cos(x) -@with_unsupported_dtypes({"2.5.1 and below": ("uint", "float16")}, backend_version) +@with_unsupported_dtypes( + {"2.6.0 and below": ("uint8", "float16", "bfloat16")}, backend_version +) def logical_not( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None ) -> paddle.Tensor: - 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.5.1 and below": ("float32", "float64", "int32", "int64", "complex")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64", "complex")}, backend_version, ) def divide( @@ -396,18 +397,19 @@ def divide( *, out: Optional[paddle.Tensor] = None, ) -> 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, ret_dtype = _elementwise_helper(x1, x2) - 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.2 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version, ) def fmin( @@ -431,7 +433,7 @@ def _apply_for_real_and_imag(fn, x1, x2): @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "float32", "float64", @@ -451,8 +453,8 @@ def greater( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) - if paddle.is_complex(x1): - 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.greater_than(x1.real(), x2.real()) imag = paddle.greater_than(x1.imag(), x2.imag()) return paddle.logical_and(real, imag) @@ -461,7 +463,7 @@ def greater( @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "bool", "float32", "float64", @@ -480,18 +482,22 @@ def greater_equal( *, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: - x1, x2, ret_dtype = _elementwise_helper(x1, x2) - 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) + x1, x2, _ = _elementwise_helper(x1, x2) + if isinstance(x1, paddle.Tensor) and isinstance(x2, paddle.Tensor): + if paddle.is_complex(x1) and paddle.is_complex(x2): + real_greater_equal = paddle.real(x1) >= paddle.real(x2) + real_equal = paddle.real(x1) == paddle.real(x2) + imag_greater_equal = paddle.imag(x1) >= paddle.imag(x2) + return paddle.logical_or( + real_greater_equal, paddle.logical_and(real_equal, imag_greater_equal) + ) + return paddle.greater_equal(x1, x2) @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", @@ -515,7 +521,7 @@ def acos(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("bool", "float32", "int32", "float64", "int64", "complex") } }, @@ -526,13 +532,14 @@ def logical_xor( ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) if paddle.is_complex(x1): - return _apply_for_real_and_imag(paddle.logical_xor, x1, x2) + x1 = paddle.cast(x1, paddle.bool) + x2 = paddle.cast(x2, paddle.bool) return paddle.logical_xor(x1, x2) @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("bool", "float32", "int32", "float64", "int64", "complex") } }, @@ -548,7 +555,7 @@ def logical_and( @with_supported_dtypes( - {"2.5.1 and below": ("bool", "float32", "int32", "float64", "int64", "complex")}, + {"2.6.0 and below": ("bool", "float32", "int32", "float64", "int64", "complex")}, backend_version, ) def logical_or( @@ -562,7 +569,7 @@ def logical_or( @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", @@ -585,7 +592,7 @@ def acosh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def sin(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -599,7 +606,7 @@ def sin(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.T @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")}, backend_version, ) def negative( @@ -619,7 +626,7 @@ def not_equal( @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("bfloat16", "float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def tanh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -638,7 +645,7 @@ def tanh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int32", @@ -663,7 +670,7 @@ def floor_divide( @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")}, backend_version, ) def bitwise_or( @@ -678,7 +685,7 @@ def bitwise_or( @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "complex")}, backend_version + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version ) def sinh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: if paddle.is_complex(x): @@ -702,7 +709,7 @@ def positive( @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -719,7 +726,7 @@ def square( @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "int32", "int64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "int32", "int64", "complex")}}, backend_version, ) def pow( @@ -760,7 +767,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.2 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 @@ -786,7 +793,7 @@ def round( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex")}, backend_version + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version ) def trunc(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: if paddle.is_complex(x): @@ -794,7 +801,7 @@ def trunc(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle return paddle.trunc(x) -@with_supported_dtypes({"2.5.2 and below": ("float64", "float32")}, backend_version) +@with_supported_dtypes({"2.6.0 and below": ("float64", "float32")}, backend_version) def trapz( y: paddle.Tensor, /, @@ -841,6 +848,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], /, @@ -853,7 +864,7 @@ def abs( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version ) def logaddexp( x1: paddle.Tensor, x2: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None @@ -866,7 +877,7 @@ def logaddexp( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def logaddexp2( x1: Union[paddle.Tensor, float, list, tuple], @@ -879,22 +890,8 @@ def logaddexp2( return ivy.log2(ivy.exp2(x1) + ivy.exp2(x2)) -@with_unsupported_device_and_dtypes( - { - "2.5.2 and below": { - "cpu": ( - "int8", - "int16", - "int32", - "int64", - "uint8", - "float16", - "float32", - "float64", - "bool", - ) - } - }, +@with_supported_dtypes( + {"2.6.0 and below": ("complex",)}, backend_version, ) def real(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -902,7 +899,7 @@ def real(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def tan(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -913,7 +910,7 @@ def tan(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.T @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def atan(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -925,7 +922,7 @@ def atan(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle. @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int32", "int64", @@ -944,7 +941,7 @@ def atan2( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "complex")}, + {"2.6.0 and below": ("float32", "float64", "complex")}, backend_version, ) def log(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -954,7 +951,7 @@ def log(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.T @with_supported_dtypes( - {"2.5.1 and below": ("int32", "int64", "float32", "float64", "complex")}, + {"2.6.0 and below": ("int32", "int64", "float32", "float64", "complex")}, backend_version, ) def exp(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -966,6 +963,10 @@ def exp(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.T 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], /, @@ -977,7 +978,7 @@ def exp2( @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 subtract( x1: Union[float, paddle.Tensor], @@ -995,7 +996,7 @@ def subtract( @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "int32", "int64")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "int32", "int64")}}, backend_version, ) def remainder( @@ -1021,7 +1022,7 @@ def remainder( @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float32", "float64", "complex")}}, + {"2.6.0 and below": {"cpu": ("float32", "float64", "complex")}}, backend_version, ) def atanh(x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None) -> paddle.Tensor: @@ -1060,13 +1061,13 @@ def bitwise_left_shift( # ------# -@with_supported_dtypes({"2.5.2 and below": ("float32", "float64")}, 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: return paddle.erf(x) @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64", "complex")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64", "complex")}, backend_version, ) def minimum( @@ -1079,7 +1080,13 @@ def minimum( ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) if paddle.is_complex(x1): - use_where = True + 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( @@ -1090,7 +1097,7 @@ def minimum( @with_supported_dtypes( - {"2.5.1 and below": ("float32", "float64", "int32", "int64", "complex")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64", "complex")}, backend_version, ) def maximum( @@ -1103,7 +1110,13 @@ def maximum( ) -> paddle.Tensor: x1, x2, ret_dtype = _elementwise_helper(x1, x2) if paddle.is_complex(x1): - use_where = True + 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 @@ -1113,7 +1126,7 @@ def maximum( @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float32", "float64", ) @@ -1127,7 +1140,7 @@ def reciprocal( @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 deg2rad( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None @@ -1136,7 +1149,7 @@ def deg2rad( @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 rad2deg( x: paddle.Tensor, /, *, out: Optional[paddle.Tensor] = None @@ -1163,6 +1176,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, @@ -1175,7 +1192,7 @@ def fmod( return paddle_backend.where(paddle_backend.less(x1, 0), -res, res) -@with_supported_dtypes({"2.5.2 and below": ("int32", "int64")}, backend_version) +@with_supported_dtypes({"2.6.0 and below": ("int32", "int64")}, backend_version) def lcm( x1: paddle.Tensor, x2: paddle.Tensor, @@ -1188,7 +1205,7 @@ def lcm( @with_supported_dtypes( { - "2.5.1 and below": ( + "2.6.0 and below": ( "float32", "float64", "complex", @@ -1210,7 +1227,7 @@ def angle( @with_supported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("int32", "int64")}}, backend_version + {"2.6.0 and below": {"cpu": ("int32", "int64")}}, backend_version ) def gcd( x1: Union[paddle.Tensor, int, list, tuple], @@ -1223,7 +1240,7 @@ def gcd( return paddle.gcd(x1, x2) -@with_supported_dtypes({"2.5.2 and below": ("complex",)}, 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/activations.py b/ivy/functional/backends/paddle/experimental/activations.py index 8d13b487369da..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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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,7 @@ def tanhshrink( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("bfloat16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, backend_version ) def threshold( x: paddle.Tensor, @@ -188,7 +191,7 @@ def threshold( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("bfloat16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, backend_version ) def softshrink( x: paddle.Tensor, /, *, lambd: float = 0.5, out: Optional[paddle.Tensor] = None @@ -204,7 +207,7 @@ def softshrink( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("bfloat16", "float16")}}, backend_version + {"2.6.0 and below": {"cpu": ("bfloat16", "float16")}}, backend_version ) def celu( x: paddle.Tensor, @@ -219,7 +222,7 @@ def celu( @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("uint16", "float16", "float32", "float64"), } @@ -238,7 +241,7 @@ def scaled_tanh( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float16", "bfloat16")}}, + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, backend_version, ) def hardshrink( @@ -252,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 4a0da45868140..dda4e9820a368 100644 --- a/ivy/functional/backends/paddle/experimental/creation.py +++ b/ivy/functional/backends/paddle/experimental/creation.py @@ -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 @@ -183,7 +183,7 @@ def unsorted_segment_sum( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -257,7 +257,7 @@ def unsorted_segment_mean( @with_unsupported_device_and_dtypes( { - "2.5.2 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 e73890115fa69..92a9a1e7f9cdb 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.2 and below": ( + "2.6.0 and below": ( "float32", "float64", "int32", @@ -42,7 +42,7 @@ def amax( @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "float32", "float64", "int32", @@ -63,7 +63,7 @@ def amin( @with_supported_dtypes( - {"2.5.2 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.2 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.2 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16", "bfloat16")}}, 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,7 @@ def copysign( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("uint8", "int8", "int16", "float16")}}, + {"2.6.0 and below": {"cpu": ("uint8", "int8", "int16", "float16")}}, backend_version, ) def nansum( @@ -162,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) @@ -172,23 +175,23 @@ def nansum( @with_unsupported_device_and_dtypes( - {"2.5.2 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.2 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], @@ -214,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], /, @@ -237,7 +243,7 @@ def hypot( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -258,14 +264,17 @@ 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_supported_dtypes( + {"2.6.0 and below": ("int32", "int64", "float64", "float32")}, backend_version +) def fix( x: paddle.Tensor, /, @@ -277,7 +286,7 @@ def fix( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float16",)}}, backend_version + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version ) def nextafter( x1: paddle.Tensor, @@ -318,7 +327,7 @@ def nextafter( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -396,16 +405,16 @@ def _np_ndim(x): @with_supported_dtypes( - {"2.5.2 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.""" @@ -644,7 +653,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: @@ -654,7 +663,7 @@ def count_nonzero( @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "complex64", "complex128", "float32", @@ -669,11 +678,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( @@ -697,45 +717,53 @@ def digamma( # --- erfc --- # # Polynomials for computing erf/erfc. Originally from cephes library. # https://netlib.org/cephes/doubldoc.html -kErfcPCoefficient = paddle.to_tensor([ - 2.46196981473530512524e-10, - 5.64189564831068821977e-1, - 7.46321056442269912687e0, - 4.86371970985681366614e1, - 1.96520832956077098242e2, - 5.26445194995477358631e2, - 9.34528527171957607540e2, - 1.02755188689515710272e3, - 5.57535335369399327526e2, -]) -kErfcQCoefficient = paddle.to_tensor([ - 1.00000000000000000000e0, - 1.32281951154744992508e1, - 8.67072140885989742329e1, - 3.54937778887819891062e2, - 9.75708501743205489753e2, - 1.82390916687909736289e3, - 2.24633760818710981792e3, - 1.65666309194161350182e3, - 5.57535340817727675546e2, -]) -kErfcRCoefficient = paddle.to_tensor([ - 5.64189583547755073984e-1, - 1.27536670759978104416e0, - 5.01905042251180477414e0, - 6.16021097993053585195e0, - 7.40974269950448939160e0, - 2.97886665372100240670e0, -]) -kErfcSCoefficient = paddle.to_tensor([ - 1.00000000000000000000e0, - 2.26052863220117276590e0, - 9.39603524938001434673e0, - 1.20489539808096656605e1, - 1.70814450747565897222e1, - 9.60896809063285878198e0, - 3.36907645100081516050e0, -]) +kErfcPCoefficient = paddle.to_tensor( + [ + 2.46196981473530512524e-10, + 5.64189564831068821977e-1, + 7.46321056442269912687e0, + 4.86371970985681366614e1, + 1.96520832956077098242e2, + 5.26445194995477358631e2, + 9.34528527171957607540e2, + 1.02755188689515710272e3, + 5.57535335369399327526e2, + ] +) +kErfcQCoefficient = paddle.to_tensor( + [ + 1.00000000000000000000e0, + 1.32281951154744992508e1, + 8.67072140885989742329e1, + 3.54937778887819891062e2, + 9.75708501743205489753e2, + 1.82390916687909736289e3, + 2.24633760818710981792e3, + 1.65666309194161350182e3, + 5.57535340817727675546e2, + ] +) +kErfcRCoefficient = paddle.to_tensor( + [ + 5.64189583547755073984e-1, + 1.27536670759978104416e0, + 5.01905042251180477414e0, + 6.16021097993053585195e0, + 7.40974269950448939160e0, + 2.97886665372100240670e0, + ] +) +kErfcSCoefficient = paddle.to_tensor( + [ + 1.00000000000000000000e0, + 2.26052863220117276590e0, + 9.39603524938001434673e0, + 1.20489539808096656605e1, + 1.70814450747565897222e1, + 9.60896809063285878198e0, + 3.36907645100081516050e0, + ] +) # Evaluate the polynomial given coefficients and `x`. @@ -748,13 +776,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) == () @@ -763,7 +792,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.2 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: @@ -802,3 +831,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 4adb2e37d3a9b..2464dffbc17f6 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.2 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.2 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.2 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -301,7 +301,7 @@ def dct( @with_unsupported_dtypes( - {"2.5.2 and below": ("bfloat16", "bool", "float16")}, backend_version + {"2.6.0 and below": ("bfloat16", "bool", "float16")}, backend_version ) def fft( x: paddle.Tensor, @@ -345,7 +345,7 @@ def fft( @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("bfloat16", "float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -367,7 +367,7 @@ def dropout1d( @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("bfloat16", "float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -389,7 +389,7 @@ def dropout2d( @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("bfloat16", "float32", "float64"), "gpu": ("bfloat16", "float16", "float32", "float64"), } @@ -422,7 +422,7 @@ def ifft( @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("int8", "float32", "float64"), "gpu": ("int8", "bfloat16", "float16", "float32", "float64"), }, @@ -469,7 +469,35 @@ def interpolate( antialias: Optional[bool] = False, out: Optional[paddle.Tensor] = None, ): - raise IvyNotImplementedException() + if mode not in ["linear", "bilinear", "bicubic", "trilinear"]: + align_corners = None + return paddle.nn.functional.interpolate( + x, + size=size, + scale_factor=scale_factor, + mode=mode, + align_corners=align_corners, + ) + + +interpolate.partial_mixed_handler = ( + lambda *args, **kwargs: kwargs.get("mode", "linear") + not in [ + "tf_area", + "nd", + "tf_bicubic", + "mitchellcubic", + "lanczos3", + "lanczos5", + "gaussian", + ] + and ( + kwargs.get("mode", "linear") in ["linear", "bilinear", "bicubic", "trilinear"] + or not kwargs.get("align_corners", False) + ) + and not kwargs.get("antialias", False) + and not kwargs.get("recompute_scale_factor", False) +) def adaptive_max_pool2d( @@ -514,7 +542,7 @@ def rfft( @with_unsupported_dtypes( - {"2.5.2 and below": ("bfloat16", "float16", "complex64", "complex128", "bool")}, + {"2.6.0 and below": ("bfloat16", "float16", "complex64", "complex128", "bool")}, backend_version, ) def rfftn( @@ -531,7 +559,7 @@ def rfftn( @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "complex64", "complex128", ) @@ -553,7 +581,7 @@ def fft2( # stft @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "complex64", "complex128", ) diff --git a/ivy/functional/backends/paddle/experimental/linear_algebra.py b/ivy/functional/backends/paddle/experimental/linear_algebra.py index aa76b96d31996..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.2 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.2 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,7 @@ def adjoint( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("int8", "uint8", "int16", "float16")}}, + {"2.6.0 and below": {"cpu": ("int8", "uint8", "int16", "float16")}}, backend_version, ) def solve_triangular( @@ -131,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.2 and below": { + "2.6.0 and below": { "cpu": ( "float32", "float64", @@ -168,7 +179,7 @@ def dot( @with_supported_device_and_dtypes( { - "2.5.2 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 a6a4b4973bf89..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.2 and below": { + "2.6.0 and below": { "cpu": ( "float16", "int8", @@ -42,7 +42,7 @@ def l1_loss( @with_unsupported_device_and_dtypes( { - "2.5.2 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.2 and below": { + "2.6.0 and below": { "cpu": ( "float16", "int8", @@ -100,7 +100,7 @@ def huber_loss( @with_unsupported_device_and_dtypes( { - "2.5.2 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.2 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.2 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 61fdaae94fd93..5464e48258825 100644 --- a/ivy/functional/backends/paddle/experimental/manipulation.py +++ b/ivy/functional/backends/paddle/experimental/manipulation.py @@ -20,6 +20,7 @@ with_unsupported_device_and_dtypes, with_supported_dtypes, with_unsupported_dtypes, + handle_out_argument, ) import paddle import ivy @@ -95,7 +96,7 @@ @with_unsupported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int16", "int8", "uint8", @@ -121,7 +122,7 @@ def moveaxis( @with_supported_dtypes( - {"2.5.2 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, backend_version, ) def pad( @@ -187,7 +188,7 @@ def pad( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -212,7 +213,7 @@ def heaviside( @with_unsupported_dtypes( - {"2.5.2 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, backend_version, ) def flipud( @@ -237,7 +238,7 @@ def vstack( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("int16", "bfloat16")}}, + {"2.6.0 and below": {"cpu": ("int16", "bfloat16")}}, backend_version, ) def hstack( @@ -254,7 +255,7 @@ def hstack( @with_unsupported_dtypes( - {"2.5.2 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, backend_version, ) def rot90( @@ -270,7 +271,7 @@ def rot90( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128")}}, backend_version, ) def top_k( @@ -297,7 +298,7 @@ def top_k( @with_unsupported_dtypes( - {"2.5.2 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, + {"2.6.0 and below": ("bfloat16", "float16", "int16", "int8", "uint8")}, backend_version, ) def fliplr( @@ -310,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, /, @@ -465,7 +470,7 @@ def atleast_2d( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("float16",)}}, + {"2.6.0 and below": {"cpu": ("float16",)}}, backend_version, ) def atleast_3d( @@ -490,7 +495,7 @@ def atleast_3d( @with_unsupported_dtypes( - {"2.5.2 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( @@ -593,6 +598,14 @@ def expand( copy: Optional[bool] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: + shape = list(shape) + n_extra_dims = len(shape) - x.ndim + if n_extra_dims > 0: + with ivy.ArrayMode(False): + x = paddle_backend.expand_dims(x, tuple(range(n_extra_dims))) + for i, dim in enumerate(shape): + if dim < 0: + shape[i] = x.shape[i] return paddle_backend.broadcast_to(x, shape) @@ -612,7 +625,7 @@ def concat_from_sequence( @with_unsupported_device_and_dtypes( - {"2.5.2 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, @@ -675,7 +688,7 @@ def unique_consecutive( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("int8", "int16", "uint8", "float16")}}, + {"2.6.0 and below": {"cpu": ("int8", "int16", "uint8", "float16")}}, backend_version, ) def fill_diagonal( @@ -741,7 +754,7 @@ def _take_with_axis( @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("int64", "float64", "int32", "uint8", "float32", "bool") } }, @@ -774,7 +787,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, " @@ -784,7 +797,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)) @@ -878,7 +891,7 @@ def trim_zeros(a: paddle.Tensor, /, *, trim: Optional[str] = "bf") -> paddle.Ten @with_supported_dtypes( - {"2.5.2 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, @@ -905,3 +918,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 c36bf0dda786f..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.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -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,7 +105,7 @@ def batch_norm( ) -@with_supported_dtypes({"2.5.2 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: Optional[int] = None, out: paddle.Tensor = None ) -> paddle.Tensor: diff --git a/ivy/functional/backends/paddle/experimental/random.py b/ivy/functional/backends/paddle/experimental/random.py index 9e1d00a6d3262..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.2 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 9a1f7870a323d..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.2 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 7572b28f0e8d0..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.2 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.2 + # 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.2 and below": ("complex", "float32", "float64", "int64")}, backend_version + {"2.6.0 and below": ("complex", "float32", "float64", "int64")}, backend_version ) def nanmean( a: paddle.Tensor, @@ -101,7 +101,7 @@ def _validate_quantile(q): @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -140,7 +140,7 @@ def nanmin( return result -@with_supported_dtypes({"2.5.2 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.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -382,7 +382,7 @@ def histogram( @with_supported_dtypes( - {"2.5.2 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.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -433,7 +433,7 @@ def unravel_index( @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -556,7 +556,7 @@ def cov( @with_supported_dtypes( - {"2.5.2 and below": ("complex", "bool", "float32", "float64")}, + {"2.6.0 and below": ("complex", "bool", "float32", "float64")}, backend_version, ) def cummax( @@ -680,8 +680,17 @@ def __get_index(lst, indices=None, prefix=None): return indices -@with_unsupported_device_and_dtypes( - {"2.5.2 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 88a2e8c591409..e043ecce4f5b7 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 @@ -10,7 +13,7 @@ # local import ivy import ivy.functional.backends.paddle as paddle_backend -from ivy.func_wrapper import with_unsupported_device_and_dtypes +from ivy.func_wrapper import with_unsupported_device_and_dtypes, with_unsupported_dtypes from ivy.functional.ivy.general import _broadcast_to from ivy.utils.exceptions import _check_inplace_update_support from . import backend_version @@ -69,11 +72,13 @@ def _squeeze_helper(query, x_ndim): ) if any(slice_squeeze): - squeeze_indices = tuple([ - idx - for idx, val in enumerate(slice_squeeze) - if (val is False and query[idx] is not None) - ]) + squeeze_indices = tuple( + [ + idx + for idx, val in enumerate(slice_squeeze) + if (val is False and query[idx] is not None) + ] + ) elif return_scalar: squeeze_indices = () else: @@ -82,9 +87,61 @@ def _squeeze_helper(query, x_ndim): return squeeze_indices +def _make_non_negative(query, x): + """Converts negative values inside the tensors in the query to their + positive form. + + Returns ``query`` unmodified if it is not a ``list``, ``tuple`` + or ``paddle.Tensor``. + + This function leaves non-tensor values in ``query`` as is. + """ + if isinstance(query, paddle.Tensor): + query[query < 0] = x.shape[0] + query[query < 0] + return query + + if not isinstance(query, (list, tuple)): + return query + + found_ellipsis = False + shape_i = 0 + for q in query: + if q is None: + continue + + if not isinstance(q, paddle.Tensor): + shape_i += 1 + continue + + if q is Ellipsis: + found_ellipsis = True + break + + q[q < 0] = x.shape[shape_i] + q[q < 0] + shape_i += 1 + + if not found_ellipsis: + return query + + shape_i = x.ndim - 1 + for q in reversed(query): + if q is None: + continue + + if not isinstance(q, paddle.Tensor): + shape_i -= 1 + continue + + if q is Ellipsis: + return query + + q[q < 0] = x.shape[shape_i] + q[q < 0] + shape_i -= 1 + + @with_unsupported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("int8", "int16", "float16", "complex64", "complex128") } }, @@ -99,14 +156,16 @@ def get_item( ) -> paddle.Tensor: if copy: x = paddle.clone(x) - if ( isinstance(query, paddle.Tensor) and query.dtype == paddle.bool and query.ndim == 0 ) or isinstance(query, bool): # special case to handle scalar boolean indices - if query is True: + if isinstance(query, paddle.Tensor): + query = query.item() + + if query: return x[None] else: return paddle.zeros(shape=[0] + x.shape, dtype=x.dtype) @@ -120,6 +179,7 @@ def get_item( squeeze_indices = _squeeze_helper(query, x.ndim) # regular queries x[idx_1,idx_2,...,idx_i] # array queries idx = Tensor(idx_1,idx_2,...,idx_i), x[idx] + query = _make_non_negative(query, x) ret = x.__getitem__(query) return ret.squeeze(squeeze_indices) if squeeze_indices else ret @@ -226,6 +286,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, @@ -268,6 +332,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] @@ -355,6 +421,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 @@ -443,6 +513,9 @@ def scatter_flat( ) +@with_unsupported_dtypes( + {"2.15.0 and below": ("uint8", "int8", "int16", "float16")}, backend_version +) def scatter_nd( indices: paddle.Tensor, updates: paddle.Tensor, @@ -517,9 +590,6 @@ def scatter_nd( updates = ivy.maximum(ivy.gather_nd(target, indices), updates).data elif reduction == "sum": updates = ivy.add(ivy.gather_nd(target, indices), updates).data - if indices.ndim <= 1: - indices = ivy.expand_dims(indices, axis=0).data - updates = ivy.expand_dims(updates, axis=0).data updates_ = _broadcast_to(ivy.gather_nd(target, indices), expected_shape).data target_dtype = target.dtype if target_dtype in [ @@ -646,7 +716,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 349b8218996ad..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 @@ -102,7 +103,7 @@ def grad_(x): @with_unsupported_device_and_dtypes( - {"2.5.2 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,),) @@ -115,10 +116,12 @@ def execute_with_gradients( xs = xs1 if isinstance(xs, ivy.Container): duplicate_indices = list( - chain.from_iterable([ - map(lambda x: x.split("/"), duplicate_index_chain[1:]) - for duplicate_index_chain in required_duplicate_index_chains - ]) + chain.from_iterable( + [ + map(lambda x: x.split("/"), duplicate_index_chain[1:]) + for duplicate_index_chain in required_duplicate_index_chains + ] + ) ) xs = ivy.set_nest_at_indices(xs, duplicate_indices, None, shallow=False) diff --git a/ivy/functional/backends/paddle/layers.py b/ivy/functional/backends/paddle/layers.py index 9a27ab9272cb1..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 @@ -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.2 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.2 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.2 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.2 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 16592ed2f4e1d..1a037d570f32a 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.2 and below": { + "2.6.0 and below": { "cpu": ( "int8", "int16", @@ -91,7 +92,7 @@ def _cross(x1, x2, axisa, axisb, axisc, axis): @with_unsupported_device_and_dtypes( - {"2.5.2 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.2 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.2 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).to_native() axis_ = list(axis) # paddle.moveaxis doesn't support tuple axes if ord == "nuc": x = paddle.moveaxis(x, axis_, [-2, -1]) @@ -276,14 +280,14 @@ def matrix_norm( ) elif ord == 1: ret = paddle_backend.max( - paddle.sum(paddle_backend.abs(x), axis=axis[0], keepdim=True), - axis=axis, + paddle.sum(paddle.abs(x), axis=axis[0], keepdim=True), + axis=[axis[1], axis[0]], keepdims=keepdims, ) elif ord == -1: ret = paddle_backend.min( - paddle.sum(paddle_backend.abs(x), axis=axis[0], keepdim=True), - axis=axis, + paddle.sum(paddle.abs(x), axis=axis[0], keepdim=True), + axis=[axis[1], axis[0]], keepdims=keepdims, ) elif ord == 2: @@ -334,7 +338,7 @@ def eig( @with_unsupported_device_and_dtypes( - {"2.5.2 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.2 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: @@ -441,7 +453,7 @@ def tensorsolve( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("complex64", "complex128")}}, + {"2.6.0 and below": {"cpu": ("complex64", "complex128", "float16")}}, backend_version, ) def qr( @@ -457,7 +469,7 @@ def qr( @with_unsupported_device_and_dtypes( - {"2.5.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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 03dc9acca403a..900f684a6e85c 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.2 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.2 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.2 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.2 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.2 and below": {"cpu": ("int16", "uint8", "int8", "float16")}}, + {"2.6.0 and below": {"cpu": ("int16", "uint8", "int8", "float16")}}, backend_version, ) def stack( @@ -221,7 +243,7 @@ def stack( first_shape = arrays[0].shape if any(arr.shape != first_shape for arr in arrays): - raise Exception("Shapes of all inputs must match") + 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.2 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.2 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def repeat( @@ -335,7 +357,7 @@ def repeat( @with_unsupported_dtypes( - {"2.5.2 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.2 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, @@ -431,6 +470,10 @@ def swapaxes( return paddle_backend.permute_dims(x, axes) +@with_supported_dtypes( + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, + backend_version, +) def clip( x: paddle.Tensor, /, @@ -462,7 +505,7 @@ def clip( @with_unsupported_dtypes( - {"2.5.2 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 c60fd5e24efea..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.2 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.2 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.2 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.2 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 d5c6a6ffbb9da..9dfedd2b8f584 100644 --- a/ivy/functional/backends/paddle/searching.py +++ b/ivy/functional/backends/paddle/searching.py @@ -16,7 +16,7 @@ @with_supported_dtypes( - {"2.5.2 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.2 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.2 and below": ("float16", "int8", "uint8")}, backend_version + {"2.6.0 and below": ("float16", "int8", "uint8")}, backend_version ) def nonzero( x: paddle.Tensor, @@ -119,6 +119,7 @@ def nonzero( return res.T +@with_unsupported_dtypes({"2.6.0 and below": ("bfloat16", "float16")}, backend_version) def where( condition: paddle.Tensor, x1: Union[float, int, paddle.Tensor], @@ -161,7 +162,7 @@ def where( @with_unsupported_dtypes( - {"2.5.2 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 aeedd6bae6d05..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.2 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, @@ -63,12 +63,14 @@ def unique_all( axis = 0 values_ = paddle.moveaxis(values, axis, 0) values_ = paddle.reshape(values_, (values_.shape[0], -1)) - sort_idx = paddle.to_tensor([ - i[0] - for i in sorted( - enumerate(values_.numpy().tolist()), key=lambda x: tuple(x[1]) - ) - ]) + sort_idx = paddle.to_tensor( + [ + i[0] + for i in sorted( + enumerate(values_.numpy().tolist()), key=lambda x: tuple(x[1]) + ) + ] + ) values = paddle.gather(values, sort_idx, axis=axis) counts = paddle.gather(counts, sort_idx) indices = paddle.gather(indices, sort_idx) @@ -86,7 +88,7 @@ def unique_all( @with_supported_dtypes( - {"2.5.2 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) @@ -109,7 +111,7 @@ def unique_counts(x: paddle.Tensor, /) -> Tuple[paddle.Tensor, paddle.Tensor]: @with_supported_dtypes( - {"2.5.2 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, @@ -135,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) @@ -144,7 +146,7 @@ def unique_inverse( @with_supported_dtypes( - {"2.5.2 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 0585c975204f9..5aae3056bc2fd 100644 --- a/ivy/functional/backends/paddle/sorting.py +++ b/ivy/functional/backends/paddle/sorting.py @@ -9,7 +9,7 @@ @with_supported_dtypes( - {"2.5.2 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.2 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.2 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,11 @@ def searchsorted( @with_unsupported_device_and_dtypes( - {"2.5.2 and below": {"cpu": ("int8", "uint8", "int16", "float16", "complex")}}, + { + "2.6.0 and below": { + "cpu": ("int8", "uint8", "int16", "float16", "bfloat16", "complex") + } + }, backend_version, ) def msort( diff --git a/ivy/functional/backends/paddle/statistical.py b/ivy/functional/backends/paddle/statistical.py index 9cc49c2733942..6b231f3161d26 100644 --- a/ivy/functional/backends/paddle/statistical.py +++ b/ivy/functional/backends/paddle/statistical.py @@ -8,7 +8,6 @@ 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 @@ -22,7 +21,7 @@ @with_supported_dtypes( - {"2.5.2 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def min( @@ -31,15 +30,57 @@ 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 + + def axis_condition(axis): + if axis is None: + return False, False + else: + axis_ = axis + if not isinstance(axis, Sequence): + axis_ = [axis] + if paddle.is_complex(x): + condition_complex_imag = any([x.imag().shape[dim] > 1 for dim in axis_]) + condition_complex_real = any([x.real().shape[dim] > 1 for dim in axis_]) + return condition_complex_real, condition_complex_imag + else: + condition_real = any([x.shape[dim] > 1 for dim in axis_]) + return condition_real, True + if paddle.is_complex(x): - real = paddle.amin(x.real(), axis=axis, keepdim=keepdims) - imag = paddle.amin(x.imag(), axis=axis, keepdim=keepdims) + real = ( + paddle.amin(x.real(), axis=axis, keepdim=keepdims) + if axis_condition(axis)[0] + else paddle.min(x.real(), axis=axis, keepdim=keepdims) + ) + imag = ( + paddle.amin(x.imag(), axis=axis, keepdim=keepdims) + if axis_condition(axis)[1] + else paddle.min(x.imag(), axis=axis, keepdim=keepdims) + ) ret = paddle.complex(real, imag) else: - ret = paddle.amin(x, axis=axis, keepdim=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 + ) + 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) + if axis_condition(axis)[0] + else paddle.min(x, axis=axis, keepdim=keepdims) + ) # The following code is to simulate other frameworks # output shapes behaviour since min output dim is 1 in paddle if isinstance(axis, Sequence): @@ -47,11 +88,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.2 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def max( @@ -63,20 +107,48 @@ def max( out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: ret_dtype = x.dtype + + def axis_condition(axis): + if axis is None: + return False, False + else: + axis_ = axis + if not isinstance(axis, Sequence): + axis_ = [axis] + if paddle.is_complex(x): + condition_complex_imag = any([x.imag().shape[dim] > 1 for dim in axis_]) + condition_complex_real = any([x.real().shape[dim] > 1 for dim in axis_]) + return condition_complex_real, condition_complex_imag + else: + condition_real = any([x.shape[dim] > 1 for dim in axis_]) + return condition_real, True + if paddle.is_complex(x): const = paddle.to_tensor(1j, dtype=x.dtype) - real_max = paddle.max(x.real(), axis=axis, keepdim=keepdims) + real_max = ( + paddle.amax(x.real(), axis=axis, keepdim=keepdims) + if axis_condition(axis)[0] + else paddle.max(x.real(), axis=axis, keepdim=keepdims) + ) imag = paddle.where( x.real() == real_max, x.imag(), paddle.full_like(x.imag(), -1e10) ) # we consider the number with the biggest real and imag part - img_max = paddle.max(imag, axis=axis, keepdim=keepdims) + img_max = ( + paddle.amax(imag, axis=axis, keepdim=keepdims) + if axis_condition(axis)[1] + else paddle.max(x.real(), axis=axis, keepdim=keepdims) + ) img_max = paddle.cast(img_max, x.dtype) return paddle.add( paddle.cast(real_max, x.dtype), paddle.multiply(img_max, const) ) else: - ret = paddle.amax(x, axis=axis, keepdim=keepdims) + ret = ( + paddle.amax(x, axis=axis, keepdim=keepdims) + if axis_condition(axis)[0] + else paddle.max(x, axis=axis, keepdim=keepdims) + ) # The following code is to simulate other frameworks # output shapes behaviour since min output dim is 1 in paddle @@ -89,17 +161,19 @@ def max( @with_supported_dtypes( - {"2.5.2 and below": ("bool", "complex", "float32", "float64")}, backend_version + {"2.6.0 and below": ("bool", "complex", "float32", "float64")}, backend_version ) def mean( x: paddle.Tensor, /, - *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + *, + dtype: Optional[paddle.dtype] = None, out: Optional[paddle.Tensor] = None, ) -> paddle.Tensor: - ret_dtype = x.dtype + if dtype is not None: + x = ivy.astype(x, dtype).to_native() if paddle.is_complex(x): ret = paddle.complex( paddle.mean(x.real(), axis=axis, keepdim=keepdims), @@ -115,11 +189,11 @@ def mean( axis = None if (x.ndim == 1 or axis is None) and not keepdims: ret = ret.squeeze() - return ret.astype(ret_dtype) + return ret @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def prod( x: paddle.Tensor, @@ -167,8 +241,8 @@ def std( return _std(x, axis, correction, keepdims).cast(x.dtype) -@with_unsupported_dtypes( - {"2.5.2 and below": ("int8", "int16", "uint8")}, +@with_supported_dtypes( + {"2.6.0 and below": ("bool", "float16", "float32", "float64", "int32", "int64")}, backend_version, ) def sum( @@ -209,7 +283,7 @@ def var( # Extra # # ----- # @with_supported_dtypes( - {"2.5.2 and below": ("complex", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("complex", "float32", "float64", "int32", "int64")}, backend_version, ) def cumprod( @@ -259,7 +333,7 @@ def cumprod( @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "int32", "int64")}, backend_version + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, backend_version ) def cumsum( x: paddle.Tensor, @@ -308,7 +382,7 @@ def cumsum( @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64", "complex64", "complex128"), "gpu": ( "bfloat16", diff --git a/ivy/functional/backends/tensorflow/__init__.py b/ivy/functional/backends/tensorflow/__init__.py index 786e8169f9139..7542c5986d466 100644 --- a/ivy/functional/backends/tensorflow/__init__.py +++ b/ivy/functional/backends/tensorflow/__init__.py @@ -18,6 +18,8 @@ import ivy from ivy.func_wrapper import _dtype_from_version +tf.experimental.numpy.experimental_enable_numpy_behavior(prefer_float32=True) + backend_version = {"version": tf.__version__} # noinspection PyUnresolvedReferences @@ -265,3 +267,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 2a9797f11897d..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) diff --git a/ivy/functional/backends/tensorflow/control_flow_ops.py b/ivy/functional/backends/tensorflow/control_flow_ops.py index e56beb4e35731..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) diff --git a/ivy/functional/backends/tensorflow/creation.py b/ivy/functional/backends/tensorflow/creation.py index 8f84e8e3cda1a..7dfee56f9f303 100644 --- a/ivy/functional/backends/tensorflow/creation.py +++ b/ivy/functional/backends/tensorflow/creation.py @@ -52,6 +52,15 @@ def arange( stop = float(start) else: stop = start + + # convert builtin types to tf scalars, as is expected by tf.range + if isinstance(start, (float, int)): + start = tf.convert_to_tensor(start) + if isinstance(stop, (float, int)): + stop = tf.convert_to_tensor(stop) + if isinstance(step, (float, int)): + step = tf.convert_to_tensor(step) + if dtype is None: if isinstance(start, int) and isinstance(stop, int) and isinstance(step, int): return tf.cast(tf.range(start, stop, delta=step, dtype=tf.int64), tf.int32) @@ -93,6 +102,13 @@ def asarray( 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 @@ -386,9 +402,9 @@ def one_hot( @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) diff --git a/ivy/functional/backends/tensorflow/data_type.py b/ivy/functional/backends/tensorflow/data_type.py index 22e8c1f0a78d6..2d0b922a2b63d 100644 --- a/ivy/functional/backends/tensorflow/data_type.py +++ b/ivy/functional/backends/tensorflow/data_type.py @@ -115,17 +115,19 @@ def broadcast_arrays( ) -> List[Union[tf.Tensor, tf.Variable]]: if len(arrays) > 1: try: - desired_shape = tf.broadcast_dynamic_shape(arrays[0].shape, arrays[1].shape) + desired_shape = tf.broadcast_dynamic_shape( + tf.shape(arrays[0]), tf.shape(arrays[1]) + ) 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: desired_shape = tf.broadcast_dynamic_shape( - desired_shape, arrays[i].shape + desired_shape, tf.shape(arrays[i]) ) 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 = [] @@ -273,10 +275,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 cff1e2e23c627..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. @@ -35,6 +34,7 @@ def dev( dv = x.device if as_native: return dv + dv = dv if dv else ivy.default_device(as_native=False) return as_ivy_dev(dv) @@ -66,7 +66,7 @@ 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, /): diff --git a/ivy/functional/backends/tensorflow/elementwise.py b/ivy/functional/backends/tensorflow/elementwise.py index ff46eefbf34ed..bbd892309c7f9 100644 --- a/ivy/functional/backends/tensorflow/elementwise.py +++ b/ivy/functional/backends/tensorflow/elementwise.py @@ -2,11 +2,11 @@ from typing import Union, Optional import tensorflow as tf - # local import ivy -from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes from ivy import promote_types_of_inputs +from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes +from ivy.utils.exceptions import IvyNotImplementedException from . import backend_version @@ -23,6 +23,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 +51,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) @@ -199,6 +202,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], /, @@ -245,6 +249,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], /, @@ -419,7 +424,7 @@ def less( return tf.math.less(x1, x2) -@with_unsupported_dtypes({"2.15.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 +436,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], /, @@ -479,7 +487,7 @@ def logaddexp( return tf.experimental.numpy.logaddexp(x1, x2) -@with_unsupported_dtypes({"2.15.0 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def real( x: Union[tf.Tensor, tf.Variable], /, @@ -699,6 +707,7 @@ def sinh( return tf.sinh(x) +@with_unsupported_dtypes({"2.15.0 and below": ("integer",)}, backend_version) def sqrt( x: Union[tf.Tensor, tf.Variable], /, @@ -733,6 +742,7 @@ def subtract( return tf.subtract(x1, x2) +@with_unsupported_dtypes({"2.15.0 and below": ("integer",)}, backend_version) def tan( x: Union[tf.Tensor, tf.Variable], /, @@ -742,6 +752,7 @@ def tan( return tf.tan(x) +@with_unsupported_dtypes({"2.15.0 and below": ("integer",)}, backend_version) def tanh( x: Union[tf.Tensor, tf.Variable], /, @@ -761,8 +772,8 @@ def trapz( axis: int = -1, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - pass # TODO: Implement purely in tensorflow + raise IvyNotImplementedException() @with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) @@ -849,19 +860,26 @@ 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.15.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": ("float16", "float32", "float64")}, + backend_version, +) def rad2deg( x: Union[tf.Tensor, tf.Variable], /, diff --git a/ivy/functional/backends/tensorflow/experimental/activations.py b/ivy/functional/backends/tensorflow/experimental/activations.py index 11c67e78af3b5..259c82c3255ce 100644 --- a/ivy/functional/backends/tensorflow/experimental/activations.py +++ b/ivy/functional/backends/tensorflow/experimental/activations.py @@ -59,7 +59,7 @@ def selu(x: Tensor, /, *, out: Optional[Tensor] = None) -> Tensor: return ivy.astype(ret, x.dtype) -@with_unsupported_dtypes({"2.15.0 and below": ("complex",)}, backend_version) +@with_supported_dtypes({"2.15.0 and below": ("float",)}, backend_version) def silu( x: Tensor, /, @@ -74,8 +74,7 @@ def silu( @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) @@ -186,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/elementwise.py b/ivy/functional/backends/tensorflow/experimental/elementwise.py index 62467bf853aac..977e0d0584c87 100644 --- a/ivy/functional/backends/tensorflow/experimental/elementwise.py +++ b/ivy/functional/backends/tensorflow/experimental/elementwise.py @@ -538,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( @@ -563,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 72501f0416178..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, @@ -174,9 +176,18 @@ def max_pool2d( ) else: padding = "VALID" - res = tf.nn.pool( - x, kernel, "MAX", strides, padding, dilations=dilation, data_format=data_format - ) + if any(d > 1 for d in dilation): + res = tf.nn.pool( + x, + kernel, + "MAX", + strides, + padding, + dilations=dilation, + data_format=data_format, + ) + 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)) @@ -1197,11 +1208,13 @@ def shape_initialization(shape, axes, x): def rank_initialization(axes): rank = tf.size(axes) - with tf.control_dependencies([ - tf.debugging.assert_less_equal( - rank, 3, message="N-D FFT supported only up to 3-D." - ) - ]): + with tf.control_dependencies( + [ + tf.debugging.assert_less_equal( + rank, 3, message="N-D FFT supported only up to 3-D." + ) + ] + ): rank = tf.identity(rank) return rank @@ -1293,9 +1306,9 @@ def static_output_shape(input_shape, shape, axes): def _right_pad_or_crop(tensor, shape): input_shape = tf.shape(tensor) shape = tf.convert_to_tensor(shape, dtype=tf.dtypes.int32) - with tf.control_dependencies([ - tf.debugging.assert_less_equal(tf.size(shape), tf.size(input_shape)) - ]): + with tf.control_dependencies( + [tf.debugging.assert_less_equal(tf.size(shape), tf.size(input_shape))] + ): shape = tf.identity(shape) shape = tf.concat([input_shape[: tf.size(input_shape) - tf.size(shape)], shape], 0) @@ -1392,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 @@ -1531,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) @@ -1666,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 4d54923e2e850..10d2f1b2c1705 100644 --- a/ivy/functional/backends/tensorflow/experimental/linear_algebra.py +++ b/ivy/functional/backends/tensorflow/experimental/linear_algebra.py @@ -1,13 +1,12 @@ 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 @@ -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,14 +228,30 @@ 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( diff --git a/ivy/functional/backends/tensorflow/experimental/losses.py b/ivy/functional/backends/tensorflow/experimental/losses.py index 6b7f032cb2060..404e2764b8d61 100644 --- a/ivy/functional/backends/tensorflow/experimental/losses.py +++ b/ivy/functional/backends/tensorflow/experimental/losses.py @@ -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 @@ -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 56ad09a9daab3..919734ace1f75 100644 --- a/ivy/functional/backends/tensorflow/experimental/manipulation.py +++ b/ivy/functional/backends/tensorflow/experimental/manipulation.py @@ -16,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 @@ -294,9 +294,8 @@ def pad( **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) - constant_values = tf.constant(constant_values) + if not isinstance(constant_values, (tf.Variable, tf.Tensor)): + constant_values = tf.constant(constant_values) if constant_values.dtype != input.dtype: constant_values = tf.cast(constant_values, input.dtype) return tf.pad( @@ -349,6 +348,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] @@ -395,7 +398,7 @@ def unique_consecutive( x_shape = None if axis is None: x_shape = x.shape - x = tf.reshape(x, -1) + x = tf.reshape(x, tf.constant([-1])) axis = -1 ndim = len(x.shape) if axis < 0: @@ -563,3 +566,27 @@ 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 + + # infer the size of any dimensions that are -1 + tf_shape = tf.constant(shape) + inferred_size = tf.reduce_prod(tf.shape(x)[dim]) // tf.reduce_prod( + tf.where(tf_shape != -1, x=shape, y=tf.constant(1)) + ) + shape = tf.where(tf_shape != -1, x=shape, y=inferred_size) + + 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 3c9c878c8fa60..ef4c5d7d5e8b6 100644 --- a/ivy/functional/backends/tensorflow/experimental/norms.py +++ b/ivy/functional/backends/tensorflow/experimental/norms.py @@ -107,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 c2742785656e3..2a1bff81f7029 100644 --- a/ivy/functional/backends/tensorflow/experimental/random.py +++ b/ivy/functional/backends/tensorflow/experimental/random.py @@ -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: Optional[str] = None, - dtype: DType, + 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/statistical.py b/ivy/functional/backends/tensorflow/experimental/statistical.py index 1febdbbf918a2..ee728a6bcbf87 100644 --- a/ivy/functional/backends/tensorflow/experimental/statistical.py +++ b/ivy/functional/backends/tensorflow/experimental/statistical.py @@ -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], /, @@ -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, @@ -555,7 +564,7 @@ def __get_index(lst, indices=None, prefix=None): @with_unsupported_dtypes( - {"2.15.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 7a018f41c9197..275770f162009 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 @@ -48,12 +49,6 @@ def current_backend_str() -> str: return "tensorflow" -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)) - ) - - def get_item( x: Union[tf.Tensor, tf.Variable], /, @@ -61,15 +56,9 @@ def get_item( *, copy: Optional[bool] = None, ) -> Union[tf.Tensor, tf.Variable]: - 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) -) + if ivy.is_array(query) and ivy.is_bool_dtype(query) and not len(query.shape): + return tf.expand_dims(x, 0) + return x[query] def to_numpy(x: Union[tf.Tensor, tf.Variable], /, *, copy: bool = True) -> np.ndarray: @@ -193,6 +182,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 @@ -323,6 +316,8 @@ def scatter_flat( if ivy.exists(size) and ivy.exists(target): ivy.utils.assertions.check_equal(len(target.shape), 1, as_array=False) ivy.utils.assertions.check_equal(target.shape[0], size, as_array=False) + if target_given: + updates = ivy.astype(updates, target.dtype) if not target_given: target = tf.zeros([size], dtype=updates.dtype) res = tf.tensor_scatter_nd_update(target, tf.expand_dims(indices, -1), updates) @@ -364,9 +359,9 @@ def scatter_nd( ) expected_shape = ( - list(indices.shape[:-1]) + list(out.shape[indices.shape[-1] :]) + list(tf.shape(indices)[:-1]) + list(out.shape[tf.shape(indices)[-1] :]) if ivy.exists(out) - else list(indices.shape[:-1]) + list(shape[indices.shape[-1] :]) + else list(tf.shape(indices)[:-1]) + list(shape[tf.shape(indices)[-1] :]) ) updates = _broadcast_to(updates, expected_shape)._data if len(updates.shape) == 0: 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 3f0ccffbcd06f..4a80b23746a81 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 @@ -28,7 +29,16 @@ def linear( bias: Optional[Union[tf.Tensor, tf.Variable]] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: - return tf.einsum("...i,...ji->...j", x, weight) + bias + # 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): @@ -44,9 +54,9 @@ def _x_dil_before_conv(x, dims, x_dilations, data_format): 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, offset + i, -offset) + x = tf.experimental.numpy.swapaxes(x, offset + i, -1) x = tf.matmul(x, h) - x = tf.experimental.numpy.swapaxes(x, -offset, offset + i) + x = tf.experimental.numpy.swapaxes(x, -1, offset + i) return x @@ -103,8 +113,14 @@ def _transpose_out_pad( + 1 for i in range(dims) ] - padding = [[0, 0], *padding, [0, 0]] - out_shape = [x_shape[0], *out_shape, filter_shape[-2]] + 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 @@ -133,7 +149,10 @@ def conv1d( 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) - res = tf.math.add(res, bias) if bias is not None else res + 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 @@ -148,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, @@ -164,14 +184,18 @@ def conv1d_transpose( x = tf.transpose(x, (0, 2, 1)) data_format = "NWC" permuted_x = True - filters = tf.transpose(filters, (0, 2, 1)) + 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, data_format, dilations ) - res = tf.math.add(res, bias) if bias is not None else res + 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 @@ -220,7 +244,10 @@ def conv2d( 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) - res = tf.math.add(res, bias) if bias is not None else res + 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 @@ -235,6 +262,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[Union[tf.Tensor, tf.Variable]] = None, @@ -251,7 +279,8 @@ def conv2d_transpose( x = tf.transpose(x, (0, 2, 3, 1)) data_format = "NHWC" permuted_x = True - filters = tf.transpose(filters, (0, 1, 3, 2)) + if filter_format == "channel_first": + filters = tf.transpose(filters, (2, 3, 1, 0)) output_shape, padding = _transpose_out_pad( x.shape, filters.shape, @@ -264,7 +293,10 @@ def conv2d_transpose( res = tf.nn.conv2d_transpose( x, filters, output_shape, strides, padding, data_format, dilations ) - res = tf.math.add(res, bias) if bias is not None else res + 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 @@ -325,7 +357,10 @@ def conv3d( 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) - res = tf.math.add(res, bias) if bias is not None else res + 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 @@ -340,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, @@ -356,7 +392,8 @@ def conv3d_transpose( x = tf.transpose(x, (0, 2, 3, 4, 1)) data_format = "NDHWC" permuted_x = True - filters = tf.transpose(filters, (0, 1, 2, 4, 3)) + 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 ) @@ -364,13 +401,18 @@ def conv3d_transpose( res = tf.nn.conv3d_transpose( x, filters, output_shape, strides, padding, data_format, dilations ) - res = tf.math.add(res, bias) if bias is not None else res + 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.15.0 and below": ("bfloat16", "complex")}, backend_version) +@with_unsupported_dtypes( + {"2.15.0 and below": ("bfloat16", "complex", "integer")}, backend_version +) def conv_general_dilated( x: Union[tf.Tensor, tf.Variable], filters: Union[tf.Tensor, tf.Variable], @@ -404,7 +446,9 @@ def conv_general_dilated( ) permuted_x = False - if data_format == "channel_first" and ivy.dev(x) == "cpu": + 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 @@ -425,27 +469,17 @@ def conv_general_dilated( dilations=dilations, ) else: - res = tf.concat( - [ - tf.nn.conv2d( - 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, - ) + 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: @@ -461,7 +495,7 @@ def conv_general_dilated( else: res = tf.concat( [ - tf.nn.conv2d( + tf.nn.conv1d( x[..., i : i + filters.shape[-2]], filters[ ..., j : j + filters.shape[-1] // feature_group_count @@ -519,7 +553,10 @@ def conv_general_dilated( ], axis=-1, ) - res = tf.math.add(res, bias) if bias is not None else res + 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 @@ -534,6 +571,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, @@ -549,6 +587,7 @@ def conv_general_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format="NWC" if data_format == "channel_last" else "NCW", dilations=dilations, bias=bias, @@ -560,6 +599,7 @@ def conv_general_transpose( strides, padding, output_shape=output_shape, + filter_format=filter_format, data_format="NHWC" if data_format == "channel_last" else "NCHW", dilations=dilations, bias=bias, @@ -571,11 +611,14 @@ def conv_general_transpose( 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)) @@ -596,9 +639,9 @@ def conv_general_transpose( filters[ ..., j : j + filters.shape[-2] // feature_group_count, : ], + output_shape, strides, - padding, - output_shape=output_shape, + padding=padding, data_format=data_format, dilations=dilations, ) @@ -616,9 +659,9 @@ def conv_general_transpose( filters[ ..., j : j + filters.shape[-2] // feature_group_count, : ], + output_shape, strides, - padding, - output_shape=output_shape, + padding=padding, data_format=data_format, dilations=dilations, ) @@ -639,9 +682,9 @@ def conv_general_transpose( filters[ ..., j : j + filters.shape[-2] // feature_group_count, : ], + output_shape, strides, - padding, - output_shape=output_shape, + padding=padding, data_format=data_format, dilations=dilations, ) @@ -658,6 +701,120 @@ def conv_general_transpose( 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: + outputs, new_states = _gpu_lstm( + x, + init_h, + init_c, + kernel, + recurrent_kernel, + bias, + recurrent_bias, + time_major, + ) + return outputs, new_states + + def nms( boxes, scores=None, diff --git a/ivy/functional/backends/tensorflow/linear_algebra.py b/ivy/functional/backends/tensorflow/linear_algebra.py index f6b412c9cb190..ca8c412a1149b 100644 --- a/ivy/functional/backends/tensorflow/linear_algebra.py +++ b/ivy/functional/backends/tensorflow/linear_algebra.py @@ -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).to_native() if ord == "nuc": x = tf.experimental.numpy.moveaxis(x, axis, (-2, -1)) ret = tf.reduce_sum( @@ -626,6 +629,7 @@ def vecdot( "float16", "bfloat16", "integer", + "complex64", ) }, backend_version, diff --git a/ivy/functional/backends/tensorflow/manipulation.py b/ivy/functional/backends/tensorflow/manipulation.py index 9ef86b5bc16bb..ed13db5d98afa 100644 --- a/ivy/functional/backends/tensorflow/manipulation.py +++ b/ivy/functional/backends/tensorflow/manipulation.py @@ -62,11 +62,56 @@ def expand_dims( out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: try: - out_shape = _calculate_out_shape(axis, x.shape) + out_shape = _calculate_out_shape(axis, tf.shape(x)) 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 flatten( + x: tf.Tensor, + /, + *, + copy: Optional[bool] = None, + start_dim: Optional[int] = 0, + end_dim: Optional[int] = -1, + order: Optional[str] = "C", + out: Optional[tf.Tensor] = None, +) -> tf.Tensor: + if x.shape == (): + x = tf.reshape(x, (1, -1))[0, :] + if start_dim == end_dim: + return ivy.inplace_update(out, x) if ivy.exists(out) else x + if start_dim not in range(-x.shape.rank, x.shape.rank): + raise IndexError( + "Dimension out of range (expected to be in range of" + f" {[-x.shape.rank, x.shape.rank - 1]}, but got {start_dim}" + ) + if end_dim not in range(-x.shape.rank, x.shape.rank): + raise IndexError( + "Dimension out of range (expected to be in range of" + f" {[-x.shape.rank, x.shape.rank - 1]}, but got {end_dim}" + ) + + # If end_dim or start_dim is negative, count them from the end + if end_dim < 0: + end_dim += x.shape.rank + if start_dim < 0: + start_dim += x.shape.rank + + if start_dim == end_dim: + return x + + in_shape = tf.shape(x) + flattened_dim = tf.math.reduce_prod(in_shape[start_dim : end_dim + 1]) + out_shape = tf.concat( + [in_shape[:start_dim], [flattened_dim], in_shape[end_dim + 1 :]], axis=0 + ) + ivy.utils.assertions.check_elem_in_list(order, ["C", "F"]) + if order == "F": + return _reshape_fortran_tf(x, out_shape) + return tf.reshape(x, out_shape) def flip( @@ -85,7 +130,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 @@ -105,7 +150,6 @@ def permute_dims( return tf.transpose(x, perm=axes) -@with_unsupported_dtypes({"2.15.0 and below": ("bool",)}, backend_version) def reshape( x: Union[tf.Tensor, tf.Variable], /, @@ -196,7 +240,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 # @@ -226,7 +270,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) diff --git a/ivy/functional/backends/tensorflow/module.py b/ivy/functional/backends/tensorflow/module.py new file mode 100644 index 0000000000000..26e8183618328 --- /dev/null +++ b/ivy/functional/backends/tensorflow/module.py @@ -0,0 +1,1705 @@ +# global +from __future__ import annotations +import re +import os +import tensorflow as tf +import functools +from tensorflow.python.util import nest +from typing import NamedTuple, Callable, Any, Tuple, List, Dict, Type, Union +import inspect +from collections import OrderedDict + + +def get_assignment_dict(): + # Traverse the call stack + lhs = None + for frame_info in inspect.stack(): + # Check if the code context is an assignment statement + if frame_info.code_context and "=" in frame_info.code_context[0]: + # Split the assignment and retrieve the LHS + lhs = frame_info.code_context[0].split("=")[0].strip() + if "self" not in lhs: + continue + break + + if not lhs: + return None, "" + + # Replace indexing with attribute access + lhs = re.sub(r"\[(\d+)\]", r".\1", lhs) + + # Split the LHS based on "." and get individual components + components = lhs.split(".") + + # Initialize the dictionary + assignment_dict = {} + + # Retrieve the live objects associated with each component + for i in range(len(components)): + # Construct the key + key = ".".join(components[: i + 1]) + + # Retrieve the value + if i == 0: + value = frame_info.frame.f_locals.get(components[i]) + else: + value = getattr(assignment_dict[".".join(components[:i])], components[i]) + + # Add the key-value pair to the dictionary + assignment_dict[key] = value + + return assignment_dict, lhs + + +def store_frame_info(fn): + @functools.wraps(fn) + def frame_info_wrapper(self, *args, **kwargs): + if self._previous_frame_info is None: + # store the info about the calling frame. + stack = inspect.stack() + self._previous_frame_info = stack[1] + res = fn(self, *args, **kwargs) + # reset the frame-info + self._previous_frame_info = None + return res + + return frame_info_wrapper + + +# 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 Layer(tf.keras.layers.Layer, 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 + _previous_frame_info = 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, + module_dict=None, + **kwargs, + ): + super(Layer, 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 = module_dict if module_dict is not None else 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, + trainable=True, + ): + _visited = _visited or {} + vs = dict() + if id(obj) in _visited: + return vs + _visited[id(obj)] = True + if isinstance(obj, Layer) and obj is not self: + fn = "_build_and_return_v" if trainable else "_build_and_return_buffers" + if not obj._built and without_initialisation: + return lambda: getattr(obj, fn)( + *obj._args, dynamic_backend=self._dynamic_backend, **obj._kwargs + ) + + return getattr(obj, fn)( + *obj._args, dynamic_backend=obj._dynamic_backend, **obj._kwargs + ) + elif isinstance(obj, tf.keras.layers.Layer) and obj is not self: + return obj.v if trainable else obj.buffers + + elif isinstance(obj, (list, tuple)): + for i, v in enumerate(obj): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + trainable=trainable, + ) + 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, + trainable=trainable, + ) + 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_", + "_args", + "_kwargs", + ) + ) + ): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + trainable=trainable, + ) + 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 _build_and_return_buffers(self, *args, **kwargs): + if not self._built: + self.build(*args, **kwargs) + return self.buffers + + @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 _compute_module_dict(self): + self._module_dict = dict() + for key, value in self.__dict__.items(): + if isinstance(value, (Layer, tf.keras.layers.Layer)): + if ( + "stateful" in value.__module__ + or hasattr(value, "_frontend_module") + or not hasattr(value, "_module_dict") + ): + 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 _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) + else: + 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(Layer, self).build(tf.TensorShape(None)) # 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(Layer, 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(Layer, self).__call__(*args, **kwargs) # noqa: UP008 + + @tf.autograph.experimental.do_not_convert + def build( + self, + *args, + from_call=False, + device=None, + dtype=None, + dynamic_backend=None, + **kwargs, + ): + self._built = True + return + + @tf.autograph.experimental.do_not_convert + def register_buffer(self, name: str, value: Union[tf.Tensor, tf.Variable]): + self._buffers.update({name: value}) + return 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(): + if isinstance(module, tf.keras.layers.Layer) and not hasattr( + module, "train" + ): + module.trainable = mode + continue + 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 `Module` class, you should implement a `call` method." + ) + + def get_config(self): + base_config = super().get_config() + config = {} + + # Get the names and values of positional arguments in __init__ + init_signature = inspect.signature(self.__init__) + arg_names = list(init_signature.parameters.keys()) + + # Include the positional arguments in the config + var_positional_arg_encountered = False + var_positional_arg_name = None + offset = 0 + for i, arg in enumerate(self._args[1:]): + arg_name = arg_names[min(i, len(arg_names) - 1)] + if var_positional_arg_encountered: + config.update( + { + f"{var_positional_arg_name}_{i - offset}": arg, + } + ) + elif ( + init_signature.parameters[arg_name].kind + == inspect.Parameter.VAR_POSITIONAL + ): + var_positional_arg_encountered = True + var_positional_arg_name = arg_name + offset = i + config.update( + { + f"{var_positional_arg_name}_{0}": arg, + } + ) + else: + config.update( + { + arg_name: arg, + } + ) + + # Include the keywords arguments in the config + kwargs = self._kwargs.copy() + kwargs.pop("devices", None) + config.update(**kwargs) + return {**base_config, **config} + + @classmethod + def from_config(cls, config): + # Get the signature of the __init__ method + init_signature = inspect.signature(cls.__init__) + arg_names = list(init_signature.parameters.keys()) + + # Separate positional and keyword arguments based on the __init__ signature + args = [] + pos_or_kw = OrderedDict() + kwargs = {} + var_positional_args = [] + for arg_name in arg_names: + if ( + arg_name in config + and init_signature.parameters[arg_name].kind + == inspect.Parameter.KEYWORD_ONLY + ): + # Handle keyword arguments + kwargs[arg_name] = config.pop(arg_name) + elif ( + arg_name in config + and init_signature.parameters[arg_name].kind + == inspect.Parameter.POSITIONAL_OR_KEYWORD + ): + # Handle positional or keyword arguments + pos_or_kw[arg_name] = config.pop(arg_name) + elif any(re.match(rf"{arg_name}_\d+", key) for key in config.keys()): + # Handle variable positional arguments + var_positional_args.extend( + [ + config.pop(key) + for key in sorted(config.keys()) + if re.match(rf"{arg_name}_\d+", key) + ] + ) + + # Unpack positional arguments and the rest as keyword arguments + config.pop("name", None) + config.pop("trainable", None) + config.pop("dtype", None) + kwargs.update(config) + + # Determine the final args and kwargs + if var_positional_args: + args = list(pos_or_kw.values()) + var_positional_args + else: + kwargs.update(pos_or_kw) + + return cls(*args, **kwargs) + + # 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 `Module` 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 # + # ---------------# + @store_frame_info + @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, (Layer, tf.keras.layers.Layer)): + _dict = getattr(self, "__dict__", None) + if _dict: + _dict[name] = value + + # compute the module dict + self._compute_module_dict() + + obj_to_search = ( + None + if not isinstance(value, (Layer, tf.keras.layers.Layer)) + else ( + self._modules + if hasattr(self, "_modules") and self._modules + else self + ) + ) + found_vars = self._find_variables( + obj=obj_to_search, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + ) + flattened_v, v_spec = tree_flatten(found_vars) + flattend_kc = v_spec.get_keychains() + for kc, v in zip(flattend_kc, flattened_v): + new_kc = kc.replace("/", ".") + if new_kc not in self.v: + self.register_parameter(new_kc, v) + + # once all variables built, find and assign buffers + found_buffers = self._find_variables( + obj=obj_to_search, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + trainable=False, + ) + flattened_buf, buf_spec = tree_flatten(found_buffers) + flattend_kc = buf_spec.get_keychains() + for kc, buf in zip(flattend_kc, flattened_buf): + new_kc = kc.replace("/", ".") + self.register_buffer(new_kc, buf) + + super().__setattr__(name, value) + return + elif isinstance(value, tf.Variable) and not name.startswith("_"): + _dict = getattr(self, "__dict__", None) + if _dict: + _dict[name] = value + # Manual solution for cases where a `tf.int32` tensor + # is placed on the GPU. TensorFlow doesn't have dedicated + # kernels for placing `tf.int32` variables on the GPU and so + # we manually cast them to `tf.int64` here otherwise due to + # `tf.config.soft_device_placement(True)` by default, + # TensorFlow puts the `tf.int32` variables on CPU which causes + # unintended consequences downstream during tracing or + # `tf.function` compilation e.g. + # Ref: https://github.com/tensorflow/tensorflow/issues/9506 + # Ref: https://stackoverflow.com/questions/44813939/could-not-satisfy-explicit-device-specification-devicegpu0-because-no-devic + dtype = ( + tf.int64 + if value.dtype == tf.int32 and "gpu:" in value.device.lower() + else value.dtype + ) + cast_dtype = dtype != value.dtype + val = ( + value + if not cast_dtype + else tf.Variable(initial_value=tf.cast(value.value(), dtype), name=name) + ) + self.register_parameter(name, val) + super().__setattr__(name, val) + return + else: + try: + obj_to_search = getattr(self, name) + except AttributeError: + obj_to_search = None + if isinstance(obj_to_search, Layer): + # retrieve all hierarchical submodules + assign_dict, kc = get_assignment_dict() + + # Iterate over all submods in assign_dict + # updating their `v` and `buffers` with the + # new value + for key, submod in assign_dict.items(): + # Get the subkey to match + subkey = kc[len(key) :].lstrip(".") + + if hasattr(submod, "v"): + for v_key, v_value in submod.v.items(): + if v_key.startswith(subkey): + submod.register_parameter(v_key, value) + + # Repeat the same process for submod.buffers + if hasattr(submod, "buffers"): + for b_key, b_value in submod.buffers.items(): + if b_key.startswith(subkey): + submod.register_buffer(b_key, value) + + # finally update the module dict + self._module_dict[name] = value + + return super().__setattr__(name, value) + + @tf.autograph.experimental.do_not_convert + def __delattr__(self, name): + if hasattr(self, name): + if isinstance(getattr(self, name), (Layer, tf.keras.layers.Layer)): + super().__delattr__(name) + 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), Layer): + 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 + + +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 + _previous_frame_info = 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, + module_dict=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 = module_dict if module_dict is not None else 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, + trainable=True, + ): + _visited = _visited or {} + vs = dict() + if id(obj) in _visited: + return vs + _visited[id(obj)] = True + if isinstance(obj, (Layer, Model)) and obj is not self: + fn = "_build_and_return_v" if trainable else "_build_and_return_buffers" + if not obj._built and without_initialisation: + return lambda: getattr(obj, fn)( + *obj._args, dynamic_backend=self._dynamic_backend, **obj._kwargs + ) + + return getattr(obj, fn)( + *obj._args, dynamic_backend=obj._dynamic_backend, **obj._kwargs + ) + elif isinstance(obj, tf.keras.layers.Layer) and obj is not self: + return obj.v if trainable else obj.buffers + + elif isinstance(obj, (list, tuple)): + for i, v in enumerate(obj): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + trainable=trainable, + ) + 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, + trainable=trainable, + ) + 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_", + "_args", + "_kwargs", + ) + ) + ): + ret = self._find_variables( + obj=v, + without_initialisation=without_initialisation, + _visited=_visited, + trainable=trainable, + ) + 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 _build_and_return_buffers(self, *args, **kwargs): + if not self._built: + self.build(*args, **kwargs) + return self.buffers + + @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, (Layer, 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 _compute_module_dict(self): + self._module_dict = dict() + for key, value in self.__dict__.items(): + if isinstance(value, (Layer, tf.keras.layers.Layer, Model, tf.keras.Model)): + if ( + "stateful" in value.__module__ + or hasattr(value, "_frontend_module") + or not hasattr(value, "_module_dict") + ): + 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 _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) + else: + 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(tf.TensorShape(None)) # 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 build( + self, + *args, + from_call=False, + device=None, + dtype=None, + dynamic_backend=None, + **kwargs, + ): + self._built = True + return + + @tf.autograph.experimental.do_not_convert + def register_buffer(self, name: str, value: Union[tf.Tensor, tf.Variable]): + self._buffers.update({name: value}) + return 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(): + if isinstance(module, tf.keras.layers.Layer) and not hasattr( + module, "train" + ): + module.trainable = mode + continue + 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 `Module` class, you should implement a `call` method." + ) + + def get_config(self): + base_config = super().get_config() + config = {} + + # Get the names and values of positional arguments in __init__ + init_signature = inspect.signature(self.__init__) + arg_names = list(init_signature.parameters.keys()) + + # Include the positional arguments in the config + var_positional_arg_encountered = False + var_positional_arg_name = None + offset = 0 + for i, arg in enumerate(self._args[1:]): + arg_name = arg_names[min(i, len(arg_names) - 1)] + if var_positional_arg_encountered: + config.update( + { + f"{var_positional_arg_name}_{i - offset}": arg, + } + ) + elif ( + init_signature.parameters[arg_name].kind + == inspect.Parameter.VAR_POSITIONAL + ): + var_positional_arg_encountered = True + var_positional_arg_name = arg_name + offset = i + config.update( + { + f"{var_positional_arg_name}_{0}": arg, + } + ) + else: + config.update( + { + arg_name: arg, + } + ) + + # Include the keywords arguments in the config + kwargs = self._kwargs.copy() + kwargs.pop("devices", None) + config.update(**kwargs) + return {**base_config, **config} + + @classmethod + def from_config(cls, config): + # Get the signature of the __init__ method + init_signature = inspect.signature(cls.__init__) + arg_names = list(init_signature.parameters.keys()) + + # Separate positional and keyword arguments based on the __init__ signature + args = [] + pos_or_kw = OrderedDict() + kwargs = {} + var_positional_args = [] + for arg_name in arg_names: + if ( + arg_name in config + and init_signature.parameters[arg_name].kind + == inspect.Parameter.KEYWORD_ONLY + ): + # Handle keyword arguments + kwargs[arg_name] = config.pop(arg_name) + elif ( + arg_name in config + and init_signature.parameters[arg_name].kind + == inspect.Parameter.POSITIONAL_OR_KEYWORD + ): + # Handle positional or keyword arguments + pos_or_kw[arg_name] = config.pop(arg_name) + elif any(re.match(rf"{arg_name}_\d+", key) for key in config.keys()): + # Handle variable positional arguments + var_positional_args.extend( + [ + config.pop(key) + for key in sorted(config.keys()) + if re.match(rf"{arg_name}_\d+", key) + ] + ) + + # Unpack positional arguments and the rest as keyword arguments + config.pop("name", None) + config.pop("trainable", None) + config.pop("dtype", None) + kwargs.update(config) + + # Determine the final args and kwargs + if var_positional_args: + args = list(pos_or_kw.values()) + var_positional_args + else: + kwargs.update(pos_or_kw) + + return cls(*args, **kwargs) + + # 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 `Module` 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 # + # ---------------# + @store_frame_info + @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, (Layer, tf.keras.layers.Layer, Model, tf.keras.Model)): + _dict = getattr(self, "__dict__", None) + if _dict: + _dict[name] = value + + # compute the module dict + self._compute_module_dict() + + obj_to_search = ( + None + if not isinstance(value, (tf.keras.layers.Layer, Layer, Model)) + else ( + self._modules + if hasattr(self, "_modules") and self._modules + else self + ) + ) + found_vars = self._find_variables( + obj=obj_to_search, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + ) + flattened_v, v_spec = tree_flatten(found_vars) + flattend_kc = v_spec.get_keychains() + for kc, v in zip(flattend_kc, flattened_v): + new_kc = kc.replace("/", ".") + if new_kc not in self.v: + self.register_parameter(new_kc, v) + + # once all variables built, find and assign buffers + found_buffers = self._find_variables( + obj=obj_to_search, + without_initialisation=( + True + if self._v_from_constructor and not self._with_partial_v + else False + ), + trainable=False, + ) + flattened_buf, buf_spec = tree_flatten(found_buffers) + flattend_kc = buf_spec.get_keychains() + for kc, buf in zip(flattend_kc, flattened_buf): + new_kc = kc.replace("/", ".") + self.register_buffer(new_kc, buf) + + super().__setattr__(name, value) + return + elif isinstance(value, tf.Variable) and not name.startswith("_"): + _dict = getattr(self, "__dict__", None) + if _dict: + _dict[name] = value + + # Manual solution for cases where a `tf.int32` tensor + # is placed on the GPU. TensorFlow doesn't have dedicated + # kernels for placing `tf.int32` variables on the GPU and so + # we manually cast them to `tf.int64` here otherwise due to + # `tf.config.soft_device_placement(True)` by default, + # TensorFlow puts the `tf.int32` variables on CPU which causes + # unintended consequences downstream during tracing or + # `tf.function` compilation e.g. + # Ref: https://github.com/tensorflow/tensorflow/issues/9506 + # Ref: https://stackoverflow.com/questions/44813939/could-not-satisfy-explicit-device-specification-devicegpu0-because-no-devic + dtype = ( + tf.int64 + if value.dtype == tf.int32 and "gpu:" in value.device.lower() + else value.dtype + ) + cast_dtype = dtype != value.dtype + val = ( + value + if not cast_dtype + else tf.Variable(initial_value=tf.cast(value.value(), dtype), name=name) + ) + self.register_parameter(name, val) + super().__setattr__(name, val) + else: + try: + obj_to_search = getattr(self, name) + except AttributeError: + obj_to_search = None + if isinstance(obj_to_search, (Model, Layer)): + # retrieve all hierarchical submodules + assign_dict, kc = get_assignment_dict() + + # Iterate over all submods in assign_dict + # updating their `v` and `buffers` with the + # new value + for key, submod in assign_dict.items(): + # Get the subkey to match + subkey = kc[len(key) :].lstrip(".") + + if hasattr(submod, "v"): + for v_key, v_value in submod.v.items(): + if v_key.startswith(subkey): + submod.register_parameter(v_key, value) + + # Repeat the same process for submod.buffers + if hasattr(submod, "buffers"): + for b_key, b_value in submod.buffers.items(): + if b_key.startswith(subkey): + submod.register_buffer(b_key, value) + + # finally update the module dict + self._module_dict[name] = value + + return super().__setattr__(name, value) + + @tf.autograph.experimental.do_not_convert + def __delattr__(self, name): + if hasattr(self, name): + if isinstance( + getattr(self, name), + (Layer, tf.keras.layers.Layer, Model, tf.keras.Model), + ): + super().__delattr__(name) + 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), (Layer, 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 8488efc1b1d9f..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. @@ -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 660576fe75bb2..0b1abe892c9e3 100644 --- a/ivy/functional/backends/tensorflow/searching.py +++ b/ivy/functional/backends/tensorflow/searching.py @@ -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 a4979773ddf4a..cc766363a3b0b 100644 --- a/ivy/functional/backends/tensorflow/set.py +++ b/ivy/functional/backends/tensorflow/set.py @@ -37,9 +37,9 @@ def unique_all( if x.dtype.is_floating and tf.reduce_any(tf.math.is_nan(values)): unique_nan = tf.math.is_nan(values) nan_index = tf.reshape(tf.where(tf.math.is_nan(x)), [-1]) - non_nan_index = tf.experimental.numpy.array([ - tensor_list.index(val) for val in values if not tf.math.is_nan(val) - ]) + non_nan_index = tf.experimental.numpy.array( + [tensor_list.index(val) for val in values if not tf.math.is_nan(val)] + ) indices = tf.experimental.numpy.full( fill_value=float("NaN"), shape=values.shape ).numpy() @@ -58,9 +58,9 @@ def unique_all( if by_value: 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(enumerate(values_), key=lambda x: tuple(x[1])) - ]) + sort_idx = tf.stack( + [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) counts = tf.gather(counts, sort_idx) diff --git a/ivy/functional/backends/tensorflow/sorting.py b/ivy/functional/backends/tensorflow/sorting.py index ee2b1d3ca997d..2d24b032d2643 100644 --- a/ivy/functional/backends/tensorflow/sorting.py +++ b/ivy/functional/backends/tensorflow/sorting.py @@ -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 5fe0d43121805..7376de7742e66 100644 --- a/ivy/functional/backends/tensorflow/statistical.py +++ b/ivy/functional/backends/tensorflow/statistical.py @@ -12,19 +12,34 @@ # -------------------# -@with_unsupported_dtypes({"2.15.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], /, @@ -55,12 +70,15 @@ def max( def mean( x: Union[tf.Tensor, tf.Variable], /, - *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + *, + dtype: Optional[tf.DType] = None, out: Optional[Union[tf.Tensor, tf.Variable]] = None, ) -> Union[tf.Tensor, tf.Variable]: axis = tuple(axis) if isinstance(axis, list) else axis + if dtype is not None: + x = ivy.astype(x, dtype).to_native() return tf.math.reduce_mean(x, axis=axis, keepdims=keepdims) @@ -163,7 +181,7 @@ def var( # ------# -@with_unsupported_dtypes({"2.15.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], /, @@ -185,6 +203,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, 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 ef672977bb4d2..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 @@ -63,6 +63,7 @@ def bernoulli( 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: 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 50b592d5d9587..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 @@ -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 15cf5702edaac..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.1 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.1 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.1 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.1 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.1 and below": (ivy.uint8,)} -valid_complex_dtypes = {"2.1.1 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.1 and below": ( + "2.2 and below": ( ivy.uint16, ivy.uint32, ivy.uint64, ) } -invalid_numeric_dtypes = {"2.1.1 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_int_dtypes = {"2.1.1 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_float_dtypes = {"2.1.1 and below": ()} -invalid_uint_dtypes = {"2.1.1 and below": (ivy.uint16, ivy.uint32, ivy.uint64)} -invalid_complex_dtypes = {"2.1.1 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 3e955b8aec7a0..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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, backend_version, ) def mish( @@ -147,7 +154,7 @@ def mish( @with_unsupported_dtypes( { - "2.1.1 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 e675c1caa6fd0..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.1 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.1 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.1 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.1 and below": {"cpu": ("float16",)}}, backend_version + {"2.2 and below": {"cpu": ("float16",)}}, backend_version ) def linspace( start: Union[torch.Tensor, float], diff --git a/ivy/functional/backends/torch/data_type.py b/ivy/functional/backends/torch/data_type.py index 37087890c10fa..76db94f8a1ae4 100644 --- a/ivy/functional/backends/torch/data_type.py +++ b/ivy/functional/backends/torch/data_type.py @@ -72,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, @@ -90,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( @@ -180,9 +181,9 @@ def as_ivy_dtype( ) -@with_unsupported_dtypes({"2.1.1 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) @@ -227,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 6fc4dbee20bd2..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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 @@ -659,7 +660,7 @@ def trapz( trapz.support_native_out = False -@with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 e4717f870ad2d..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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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,7 @@ def tanhshrink( return ivy.astype(ret, x.dtype) -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def threshold( x: torch.Tensor, /, @@ -133,7 +133,7 @@ def threshold( return ivy.astype(ret, x.dtype) -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, backend_version) +@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: @@ -154,7 +154,7 @@ def scaled_tanh( return alpha * torch.nn.functional.tanh(beta * x) -@with_unsupported_dtypes({"2.1.1 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: @@ -162,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 09ce3fbd05694..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.1 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.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def hann_window( size: int, /, @@ -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.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def blackman_window( size: int, /, diff --git a/ivy/functional/backends/torch/experimental/elementwise.py b/ivy/functional/backends/torch/experimental/elementwise.py index c7b1188fa34e5..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.1 and below": ( + "2.2 and below": ( "complex64", "complex128", ) @@ -40,7 +40,7 @@ def amax( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "complex64", "complex128", ) @@ -62,12 +62,12 @@ def amin( amin.support_native_out = True -@with_supported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 a959d5ab83e03..b6c0a7cedf6e4 100644 --- a/ivy/functional/backends/torch/experimental/gradients.py +++ b/ivy/functional/backends/torch/experimental/gradients.py @@ -34,10 +34,12 @@ def backward(ctx, upstream): def vjp(func: Callable, *primals): flattened_primals, ret_idxs = _flatten_containers(primals) - unique_keys = list({ - ivy.index_nest(ret_idxs, i) - for i in ivy.nested_argwhere(ret_idxs, lambda x: isinstance(x, str)) - }) + unique_keys = list( + { + ivy.index_nest(ret_idxs, i) + for i in ivy.nested_argwhere(ret_idxs, lambda x: isinstance(x, str)) + } + ) def grad_fn(*x_in): ret, idxs = _flatten_containers( @@ -93,10 +95,12 @@ def vjpfun(*x_in): def jvp(func: Callable, primals, tangents): flattened_primals, ret_idxs = _flatten_containers(primals) flattened_tangents, _ = _flatten_containers(tangents) - unique_keys = list({ - ivy.index_nest(ret_idxs, i) - for i in ivy.nested_argwhere(ret_idxs, lambda x: isinstance(x, str)) - }) + unique_keys = list( + { + ivy.index_nest(ret_idxs, i) + for i in ivy.nested_argwhere(ret_idxs, lambda x: isinstance(x, str)) + } + ) def grad_fn(*x_in): ret, idxs = _flatten_containers( diff --git a/ivy/functional/backends/torch/experimental/layers.py b/ivy/functional/backends/torch/experimental/layers.py index 09776b38d44aa..1c53639d23409 100644 --- a/ivy/functional/backends/torch/experimental/layers.py +++ b/ivy/functional/backends/torch/experimental/layers.py @@ -29,7 +29,7 @@ def _determine_depth_max_pooling(x, kernel, strides, dims, data_format="channel_ return x, kernel, strides, depth_pooling -@with_unsupported_dtypes({"2.1.1 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, ...]], @@ -94,7 +94,7 @@ def max_pool1d( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -170,7 +170,7 @@ def max_pool2d( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -282,7 +282,7 @@ def _get_specific_pad(x_shape, kernel, strides, padding, dims): return padding, pad_specific -@with_unsupported_dtypes({"2.1.1 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]], @@ -374,7 +374,7 @@ def _adjust_num_padded_values_to_ceil( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -478,7 +478,7 @@ def avg_pool2d( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -581,7 +581,7 @@ def avg_pool3d( return res -@with_supported_dtypes({"2.1.1 and below": ("float32", "float64")}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float32", "float64")}, backend_version) def dct( x: torch.Tensor, /, @@ -694,7 +694,7 @@ def idct( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -740,7 +740,7 @@ def fft( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", "complex", @@ -774,7 +774,7 @@ def dropout( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, backend_version, ) def dropout1d( @@ -797,7 +797,7 @@ def dropout1d( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, backend_version, ) def dropout2d( @@ -822,7 +822,7 @@ def dropout2d( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -881,7 +881,7 @@ def ifft( return torch.fft.ifft(x, n, dim, norm, out=out).resolve_conj() -@with_unsupported_dtypes({"2.1.1 and below": ("complex",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, backend_version) def embedding( weights: torch.Tensor, indices: torch.Tensor, @@ -954,24 +954,42 @@ def interpolate( ) -@with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def fft2( x: torch.Tensor, *, @@ -1037,7 +1055,7 @@ def rfft( return ret -@with_unsupported_dtypes({"2.1.1 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def rfftn( x: torch.Tensor, s: Optional[Sequence[int]] = None, @@ -1075,7 +1093,7 @@ def rfftn( # stft @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) diff --git a/ivy/functional/backends/torch/experimental/linear_algebra.py b/ivy/functional/backends/torch/experimental/linear_algebra.py index 53cb4e04c7063..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.1 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.1 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 e5b227a01f55d..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.1 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.1 and below": ( + "2.2 and below": ( "complex", "uint8", "int8", @@ -59,7 +59,7 @@ def smooth_l1_loss( @with_unsupported_dtypes( - {"2.1.1 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.1 and below": ( + "2.2 and below": ( "float16", "uint8", "int8", @@ -104,7 +104,7 @@ def soft_margin_loss( @with_supported_dtypes( - {"2.1.1 and below": ("float",)}, + {"2.2 and below": ("float",)}, backend_version, ) def kl_div( @@ -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 62162125e9137..bef36287fd95e 100644 --- a/ivy/functional/backends/torch/experimental/manipulation.py +++ b/ivy/functional/backends/torch/experimental/manipulation.py @@ -17,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 ( @@ -60,7 +64,7 @@ def heaviside( @with_supported_dtypes( - {"2.1.1 and below": ("float32", "float64", "complex64", "complex128")}, + {"2.2 and below": ("float32", "float64", "complex64", "complex128")}, backend_version, ) def pad( @@ -238,7 +242,7 @@ def fliplr( fliplr.support_native_out = False -@with_unsupported_dtypes({"2.1.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def i0( x: torch.Tensor, /, @@ -331,7 +335,7 @@ def atleast_3d( return transformed -@with_unsupported_dtypes({"2.1.1 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, @@ -409,7 +413,7 @@ def expand( expand.support_native_out = False -@with_unsupported_dtypes({"2.1.1 and below": ("complex", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("complex", "float16")}, backend_version) def unique_consecutive( x: torch.Tensor, /, @@ -439,42 +443,6 @@ def column_stack( return torch.column_stack(arrays) -@with_supported_dtypes({"2.1.1 and below": ("float32", "float64")}, backend_version) -def put_along_axis( - arr: torch.Tensor, - indices: torch.Tensor, - values: Union[int, torch.Tensor], - axis: int, - /, - *, - mode: Literal["sum", "min", "max", "mul", "replace"] = "replace", - out: Optional[torch.Tensor] = None, -) -> torch.Tensor: - mode_mappings = { - "sum": "sum", - "min": "amin", - "max": "amax", - "mul": "prod", - "replace": "replace", - } - mode = mode_mappings.get(mode, mode) - indices = indices.to(torch.int64) - if mode == "replace": - return torch.scatter(arr, axis, indices, values, out=out) - else: - return torch.scatter_reduce(arr, axis, indices, values, reduce=mode, out=out) - - -put_along_axis.partial_mixed_handler = lambda *args, mode=None, **kwargs: mode in [ - "replace", - "sum", - "mul", - "mean", - "max", - "min", -] - - def concat_from_sequence( input_sequence: Union[Tuple[torch.Tensor], List[torch.Tensor]], /, @@ -550,13 +518,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)) @@ -639,3 +607,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 6861955d2f652..e17a2c42a8e62 100644 --- a/ivy/functional/backends/torch/experimental/norms.py +++ b/ivy/functional/backends/torch/experimental/norms.py @@ -18,7 +18,7 @@ def l1_normalize( l1_normalize.support_native_out = True -@with_unsupported_dtypes({"2.1.1 and below": ("float16",)}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, backend_version) def l2_normalize( x: torch.Tensor, /, @@ -32,7 +32,7 @@ def l2_normalize( l2_normalize.support_native_out = True -@with_supported_dtypes({"2.1.1 and below": ("float",)}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float",)}, backend_version) def local_response_norm( x: torch.Tensor, size, @@ -56,7 +56,7 @@ def local_response_norm( return ret -@with_unsupported_dtypes({"2.1.1 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def batch_norm( x: torch.Tensor, mean: torch.Tensor, @@ -102,7 +102,7 @@ def batch_norm( ) -@with_unsupported_dtypes({"2.1.1 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, @@ -150,7 +150,7 @@ def instance_norm( ) -@with_unsupported_dtypes({"2.1.1 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, @@ -175,7 +175,7 @@ def group_norm( return xnormalized -@with_unsupported_dtypes({"2.1.1 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 cfc13707667a7..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.1 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.1 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.1 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 10b9ce8defd1e..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.1 + # 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.1 + # only valid for torch > 2.2 result = result[temp] return result diff --git a/ivy/functional/backends/torch/experimental/statistical.py b/ivy/functional/backends/torch/experimental/statistical.py index 3c89b0a90d592..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.1 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.1 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, /, @@ -291,10 +292,12 @@ def _handle_axis(a, q, fn, keepdims=False, axis=None): for i, s in enumerate(sorted(keep)): a = torch.moveaxis(a, s, i) - a = a.view([ - *a.shape[:nkeep], - -1, - ]) + a = a.view( + [ + *a.shape[:nkeep], + -1, + ] + ) axis_arg = -1 ret = fn(a, q, axis=axis_arg) @@ -364,7 +367,7 @@ def _compute_quantile_wrapper( ) -@with_unsupported_dtypes({"2.1.1 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], @@ -445,7 +448,7 @@ def _nanmedian(input, axis, keepdims): return ret -@with_unsupported_dtypes({"2.1.1 and below": ("bfloat16", "float16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("bfloat16", "float16")}, backend_version) def nanmedian( input: torch.Tensor, /, @@ -533,7 +536,7 @@ def igamma( igamma.support_native_out = True -@with_unsupported_dtypes({"2.1.1 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, @@ -590,7 +593,7 @@ def cov( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "complex")}, + {"2.2 and below": ("float16", "complex")}, backend_version, ) def cummax( @@ -627,7 +630,7 @@ def cummax( @with_unsupported_dtypes( { - "2.1.1 and below": ("uint8", "float16", "bfloat16"), + "2.2 and below": ("bool", "float16"), "1.12.1 and above": ("uint8", "float16"), }, backend_version, @@ -645,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 8395caf0efd10..55187d9f2ceb7 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.1 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) @@ -93,6 +96,8 @@ def get_item( *, copy: Optional[bool] = None, ) -> torch.Tensor: + if copy: + x = x.clone() return x.__getitem__(query) @@ -186,28 +191,77 @@ def gather( batch_dims %= len(params.shape) ivy.utils.assertions.check_gather_input_valid(params, indices, axis, batch_dims) result = [] + + def expand_p_i(params, indices, axis=axis, batch_dims=batch_dims): + axis %= len(params.shape) + abs(params.dim() - (indices.dim() - batch_dims)) + stack_dims1 = params.shape[:axis] + stack_dims2 = params.shape[axis + 1 :] + indices = indices.reshape( + ( + torch.Size([1 for dim in stack_dims1]) + + torch.Size([-1]) + + torch.Size([1 for dim in stack_dims2]) + ) + ) + indices = indices.expand( + (stack_dims1 + torch.Size([-1]) + stack_dims2) + ).reshape((stack_dims1 + torch.Size([-1]) + stack_dims2)) + return indices, axis + + final_shape = ( + params.shape[:axis] + indices.shape[batch_dims:] + params.shape[axis + 1 :] + ) + if batch_dims == 0: - result = torch.gather(params, axis, indices, sparse_grad=False, out=out) + dim_diff = abs(params.dim() - (indices.dim() - batch_dims)) + if dim_diff != 0: + indices_expanded, new_axis = expand_p_i(params, indices) + + result = torch.gather( + params, new_axis, indices_expanded.long(), sparse_grad=False, out=out + ).reshape( + params.shape[:axis] + + indices.shape[batch_dims:] + + params.shape[axis + 1 :] + ) + result = result.to(dtype=params.dtype) + return result + else: + indices_expanded, new_axis = expand_p_i(params, indices) + result = torch.gather( + params, new_axis, indices_expanded.long(), sparse_grad=False, out=out + ).reshape(final_shape) + result = result.to(dtype=params.dtype) + else: + indices_ex = indices + new_axis = axis + params_slices = torch.unbind(params, axis=0) if params.shape[0] > 0 else params + indices_slices = ( + torch.unbind(indices_ex, axis=0) if indices.shape[0] > 0 else indices_ex + ) for b in range(batch_dims): if b == 0: - zip_list = [(p, i) for p, i in zip(params, indices)] + zip_list = [(p, i) for p, i in zip(params_slices, indices_slices)] else: zip_list = [ (p, i) for z in [zip(p1, i1) for p1, i1 in zip_list] for p, i in z ] for z in zip_list: p, i = z - r = torch.gather( - p, (axis - batch_dims) % p.ndim, i, sparse_grad=False, out=False - ) - + i_ex, new_axis = expand_p_i(p, i, axis=axis - batch_dims) + r = torch.gather(p, (new_axis), i_ex.long(), sparse_grad=False, out=None) 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) - + result = result.reshape( + params.shape[:axis] + + max(indices.shape[batch_dims:], torch.Size([1])) + + params.shape[axis + 1 :] + ) + result = result.to(dtype=params.dtype) + if ivy.exists(out): + return ivy.inplace_update(out, result) return result @@ -229,9 +283,9 @@ def gather_nd_helper(params, indices): indices_for_flat_tiled = torch.reshape( torch.sum(indices * indices_scales, -1, keepdim=True), (-1, 1) ).repeat(*[1, implicit_indices_factor]) - implicit_indices = torch.unsqueeze( - torch.arange(implicit_indices_factor), 0 - ).repeat(*[indices_for_flat_tiled.shape[0], 1]) + implicit_indices = torch.unsqueeze(torch.arange(implicit_indices_factor), 0).repeat( + *[indices_for_flat_tiled.shape[0], 1] + ) indices_for_flat = indices_for_flat_tiled + implicit_indices flat_indices_for_flat = torch.reshape(indices_for_flat, (-1,)).type(torch.long) flat_gather = torch.gather(flat_params, 0, flat_indices_for_flat) @@ -277,6 +331,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 @@ -353,7 +411,7 @@ def multiprocessing(context: Optional[str] = None): @with_unsupported_dtypes( { - "2.1.1 and below": ("bfloat16",), + "2.2 and below": ("bfloat16",), }, backend_version, ) @@ -386,10 +444,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 @@ -405,7 +463,7 @@ def scatter_flat( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -468,19 +526,19 @@ def scatter_nd( indices_for_flat_tiled = torch.reshape( torch.sum(indices * indices_scales, -1, keepdim=True), (-1, 1) ).repeat(*[1, implicit_indices_factor]) - implicit_indices = torch.unsqueeze( - torch.arange(implicit_indices_factor), 0 - ).repeat(*[indices_for_flat_tiled.shape[0], 1]) + implicit_indices = torch.unsqueeze(torch.arange(implicit_indices_factor), 0).repeat( + *[indices_for_flat_tiled.shape[0], 1] + ) indices_for_flat = indices_for_flat_tiled + implicit_indices flat_indices_for_flat = torch.reshape(indices_for_flat, (-1,)).type(torch.long) global torch_scatter 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 @@ -512,8 +570,8 @@ def shape( return ivy.Shape(x.shape) -@with_unsupported_dtypes({"2.1.1 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, @@ -530,8 +588,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.1 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 3434409fa0509..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 diff --git a/ivy/functional/backends/torch/layers.py b/ivy/functional/backends/torch/layers.py index a90c6d81f8970..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.1 and below": ("float32", "float64", "complex")}, + {"2.2 and below": ("float32", "float64", "complex")}, backend_version, ) def multi_head_attention( @@ -116,7 +117,7 @@ def multi_head_attention( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def linear( @@ -253,7 +254,7 @@ def _tranpose_padding( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) # noinspection PyUnresolvedReferences @@ -286,7 +287,7 @@ def conv1d( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def conv1d_v_1p9p0_and_above( @@ -324,7 +325,7 @@ def conv1d_v_1p9p0_and_above( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", "complex", @@ -341,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, @@ -348,7 +350,8 @@ def conv1d_transpose( ): if data_format == "NWC": x = x.permute(0, 2, 1) - filters = filters.permute(1, 2, 0) + 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:], @@ -376,7 +379,7 @@ def conv1d_transpose( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) # noinspection PyUnresolvedReferences @@ -409,7 +412,7 @@ def conv2d( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def conv2d_v_1p9p0_and_above( @@ -447,7 +450,7 @@ def conv2d_v_1p9p0_and_above( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", "complex", @@ -464,6 +467,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[torch.Tensor] = None, @@ -471,7 +475,8 @@ def conv2d_transpose( ): if data_format == "NHWC": x = x.permute(0, 3, 1, 2) - filters = filters.permute(2, 3, 0, 1) + 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:], @@ -502,7 +507,7 @@ def conv2d_transpose( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", "complex", @@ -543,7 +548,7 @@ def depthwise_conv2d( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, backend_version + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version ) # noinspection PyUnresolvedReferences def conv3d( @@ -575,7 +580,7 @@ def conv3d( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, backend_version + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version ) def conv3d_v_1p9p0_and_above( x: torch.Tensor, @@ -611,7 +616,7 @@ def conv3d_v_1p9p0_and_above( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) # noinspection PyUnresolvedReferences @@ -623,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, @@ -630,7 +636,8 @@ def conv3d_transpose( ) -> torch.Tensor: if data_format == "NDHWC": x = x.permute(0, 4, 1, 2, 3) - filters = filters.permute(3, 4, 0, 1, 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:], @@ -662,7 +669,7 @@ def conv3d_transpose( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def conv_general_dilated( @@ -711,7 +718,7 @@ def conv_general_dilated( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def conv_general_dilated_v_1p9p0_and_above( @@ -765,7 +772,7 @@ def conv_general_dilated_v_1p9p0_and_above( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "complex")}, backend_version, ) def conv_general_transpose( @@ -777,6 +784,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_first", dilations: Union[int, Tuple[int], Tuple[int, int], Tuple[int, int, int]] = 1, feature_group_count: int = 1, @@ -785,7 +793,8 @@ def conv_general_transpose( ): if data_format == "channel_last": x = x.permute(0, dims + 1, *range(1, dims + 1)) - filters = filters.permute(dims, dims + 1, *range(dims)) + 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:], @@ -859,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 763b1f07a28dd..e8d960d313b37 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 and below": ("float16", "bfloat16", "bool")}, backend_version + {"2.2 and below": ("float16", "bfloat16", "bool")}, backend_version ) def matmul( x1: torch.Tensor, @@ -193,7 +193,9 @@ def matmul( matmul.support_native_out = True -@with_supported_dtypes({"2.1.1 and below": ("float", "complex")}, backend_version) +@with_supported_dtypes( + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, backend_version +) def matrix_norm( x: torch.Tensor, /, @@ -201,15 +203,25 @@ 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) + # ivy forces out to be the same type as the input + # but it has to be the same type as ret. + if ( + "complex" in ivy.as_ivy_dtype(dtype) or "complex" in ivy.as_ivy_dtype(x.dtype) + ) and ivy.exists(out): + out = ivy.astype(out, "float32").to_native() + 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.1 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 +235,7 @@ def eig( eig.support_native_out = True -@with_unsupported_dtypes({"2.1.1 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 +245,7 @@ def matrix_power( matrix_power.support_native_out = True -@with_unsupported_dtypes({"2.1.1 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 +293,7 @@ def matrix_transpose( return torch.swapaxes(x, -1, -2) -@with_unsupported_dtypes({"2.1.1 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 +308,7 @@ def outer( outer.support_native_out = True -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def pinv( x: torch.Tensor, /, @@ -312,7 +324,7 @@ def pinv( pinv.support_native_out = True -@with_unsupported_dtypes({"2.1.1 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 +336,7 @@ def tensorsolve( return torch.linalg.tensorsolve(x1, x2, dims=axes) -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def qr( x: torch.Tensor, /, @@ -346,7 +358,7 @@ def qr( return ret -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def slogdet( x: torch.Tensor, /, @@ -361,7 +373,7 @@ def slogdet( slogdet.support_native_out = True -@with_unsupported_dtypes({"2.1.1 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 +409,7 @@ def solve( return ret -@with_unsupported_dtypes({"2.1.1 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 +426,7 @@ def svd( return results(D) -@with_unsupported_dtypes({"2.1.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 +442,7 @@ def svdvals( # ToDo: re-add int32 support once # (https://github.com/pytorch/pytorch/issues/84530) is fixed -@with_supported_dtypes({"2.1.1 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 +461,7 @@ def tensordot( return ret -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def trace( x: torch.Tensor, /, @@ -489,7 +501,15 @@ def vecdot( vecdot.support_native_out = True -@with_unsupported_dtypes({"2.1.1 and below": ("integer",)}, backend_version) +@with_unsupported_dtypes( + { + "2.2 and below": ( + "integer", + "complex64", + ) + }, + backend_version, +) def vector_norm( x: torch.Tensor, /, @@ -515,7 +535,7 @@ def vector_norm( # ----- # -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def diag( x: torch.Tensor, /, @@ -526,7 +546,7 @@ def diag( return torch.diag(x, diagonal=k) -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, backend_version) +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, backend_version) def vander( x: torch.tensor, /, @@ -552,7 +572,7 @@ def vander( @with_unsupported_dtypes( { - "2.1.1 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 4cfb62addec6e..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 @@ -61,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 @@ -77,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, /, @@ -85,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, /, @@ -98,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 = [ @@ -146,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 = [ @@ -168,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 @@ -234,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.1 and below": ("int8", "int16", "uint8")}, backend_version -) +@with_unsupported_dtypes({"2.2 and below": ("int8", "int16", "uint8")}, backend_version) def repeat( x: torch.Tensor, /, @@ -308,7 +314,7 @@ def swapaxes( @with_unsupported_dtypes( - {"2.1.1 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 6f24af1ad998f..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.1 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 df83aee7eb286..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.1 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 b3d436fff5618..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.1 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.1 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 6f232ee2864a3..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.1 and below": ("complex", "float16"), + "2.2 and below": ("complex", "float16"), }, backend_version, ) @@ -62,11 +62,11 @@ def unique_all( else: values_ = torch.moveaxis(values, axis, 0) values_ = torch.reshape(values_, (values_.shape[0], -1)) - sort_idx = torch.tensor([ - i[0] for i in sorted(enumerate(values_), key=lambda x: tuple(x[1])) - ]) + sort_idx = torch.tensor( + [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.1 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.1 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.1 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 9e474c01d1816..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.1 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.1 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.1 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.1 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 a7651c255b030..b5ff291d030d0 100644 --- a/ivy/functional/backends/torch/statistical.py +++ b/ivy/functional/backends/torch/statistical.py @@ -7,20 +7,25 @@ # local import ivy from ivy.functional.ivy.statistical import _get_promoted_type_of_operands -from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes +from ivy.func_wrapper import ( + with_unsupported_dtypes, + with_supported_dtypes, +) from . import backend_version # Array API Standard # # -------------------# -@with_unsupported_dtypes({"2.1.1 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 +33,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,15 +84,18 @@ def max( max.support_native_out = True -@with_supported_dtypes({"2.1.1 and below": ("float", "complex")}, backend_version) +@with_supported_dtypes({"2.2 and below": ("float", "complex")}, backend_version) def mean( x: torch.Tensor, /, - *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + *, + dtype: Optional[torch.dtype] = None, out: Optional[torch.Tensor] = None, ) -> torch.Tensor: + if dtype is not None: + dtype = ivy.as_native_dtype(dtype) if axis is None: num_dims = len(x.shape) axis = list(range(num_dims)) @@ -83,7 +104,7 @@ def mean( return ivy.inplace_update(out, x) else: return x - return torch.mean(x, dim=axis, keepdim=keepdims, out=out) + return torch.mean(x, dim=axis, dtype=dtype, keepdim=keepdims, out=out) mean.support_native_out = True @@ -101,7 +122,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.1 and below": ("uint8", "float16", "bfloat16"), + "2.2 and below": ("uint8", "float16", "bfloat16"), }, backend_version, ) @@ -129,7 +150,7 @@ def prod( @with_unsupported_dtypes( - {"2.1.1 and below": ("int8", "int16", "int32", "int64", "float16")}, + {"2.2 and below": ("int8", "int16", "int32", "int64", "float16")}, backend_version, ) def std( @@ -166,7 +187,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.1 and below": ("uint8",)}, backend_version) +@with_unsupported_dtypes( + {"2.2 and below": ("uint8", "float16", "bfloat16")}, backend_version +) def sum( x: torch.Tensor, /, @@ -228,7 +251,7 @@ def var( # TODO: bfloat16 support is added in PyTorch 1.12.1 @with_unsupported_dtypes( { - "2.1.1 and below": ("uint8", "float16", "bfloat16"), + "2.2 and below": ("uint8", "float16", "bfloat16", "bool"), }, backend_version, ) @@ -275,8 +298,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 +342,7 @@ def cumsum( @with_unsupported_dtypes( - {"2.1.1 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 74b5c3b1c4b17..6e71d220f4e32 100644 --- a/ivy/functional/frontends/__init__.py +++ b/ivy/functional/frontends/__init__.py @@ -2,15 +2,16 @@ versions = { - "torch": "2.1.1", + "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.2", + "paddle": "2.6.0", "sklearn": "1.3.0", "xgboost": "1.7.6", "torchvision": "0.15.2.", + "mindspore": "2.0.0", } diff --git a/ivy/functional/frontends/jax/array.py b/ivy/functional/frontends/jax/array.py index 7e5aa872f4c04..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.2 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.2 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def argmin( self, /, 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 b2ce5a8631c81..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.20 and below": ( + "0.4.24 and below": ( "float16", "float32", "float64", @@ -309,7 +309,7 @@ def cosh(x): @with_unsupported_dtypes( - {"0.4.20 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.20 and below": ( + "0.4.24 and below": ( "float16", "float32", "float64", @@ -465,7 +465,7 @@ def imag(x): @with_unsupported_dtypes( - {"0.4.20 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 0cc778cf320cb..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.20 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 6972b2d115109..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 ---------- @@ -407,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 @@ -424,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 d426cf6939c7b..911543205382d 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.20 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.20 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.20 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) @@ -293,7 +293,6 @@ def single(x): @to_ivy_arrays_and_back def size(a, axis=None): - ivy.set_default_int_dtype("int64") if axis is not None: sh = ivy.shape(a) return sh[axis] diff --git a/ivy/functional/frontends/jax/numpy/dtype.py b/ivy/functional/frontends/jax/numpy/dtype.py index 081a3c468e272..ef686feaf4581 100644 --- a/ivy/functional/frontends/jax/numpy/dtype.py +++ b/ivy/functional/frontends/jax/numpy/dtype.py @@ -9,6 +9,13 @@ from ivy import with_supported_dtypes +@to_ivy_arrays_and_back +def astype(x, dtype, /, *, copy=True): + if not copy and dtype == x.dtype: + return x + return ivy.astype(x, dtype, copy=copy) + + @to_ivy_arrays_and_back def can_cast(from_, to, casting="safe"): ivy.utils.assertions.check_elem_in_list( diff --git a/ivy/functional/frontends/jax/numpy/fft.py b/ivy/functional/frontends/jax/numpy/fft.py index 69b9415b6176b..dadd61b25d077 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.2 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) @@ -70,6 +70,89 @@ def ifft2(a, s=None, axes=(-2, -1), norm=None): return ivy.array(ivy.ifft2(a, s=s, dim=axes, norm=norm), dtype=ivy.dtype(a)) +@with_unsupported_dtypes({"1.24.3 and below": ("complex64", "bfloat16")}, "numpy") +@to_ivy_arrays_and_back +def ifftn(a, s=None, axes=None, norm=None): + a = ivy.asarray(a, dtype=ivy.complex128) + a = ivy.ifftn(a, s=s, axes=axes, norm=norm) + return a + + +@to_ivy_arrays_and_back +def ifftshift(x, axes=None): + if not ivy.is_array(x): + raise ValueError("Input 'x' must be an array") + + # Get the shape of x + shape = ivy.shape(x) + + # If axes is None, shift all axes + if axes is None: + axes = tuple(range(x.ndim)) + + # Convert axes to a list if it's not already + axes = [axes] if isinstance(axes, int) else list(axes) + + # Perform the shift for each axis + for axis in axes: + axis_size = shape[axis] + shift = -ivy.floor(axis_size / 2).astype(ivy.int32) + result = ivy.roll(x, shift, axis=axis) + + return result + + +@to_ivy_arrays_and_back +def irfftn(a, s=None, axes=None, norm=None): + x = ivy.asarray(a) + + if axes is None: + axes = list(range(len(x.shape))) + + include_last_axis = len(x.shape) - 1 in axes + + if s is None: + s = [ + x.shape[axis] if axis != (len(x.shape) - 1) else 2 * (x.shape[axis] - 1) + for axis in axes + ] + + real_result = x + remaining_axes = [axis for axis in axes if axis != (len(x.shape) - 1)] + + if remaining_axes: + real_result = ivy.ifftn( + x, + s=[s[axes.index(axis)] for axis in remaining_axes], + axes=remaining_axes, + norm=norm, + ) + + if include_last_axis: + axis = len(x.shape) - 1 + size = s[axes.index(axis)] + freq_domain = ivy.moveaxis(real_result, axis, -1) + slices = [slice(None)] * ivy.get_num_dims(freq_domain) + slices[-1] = slice(0, size // 2 + 1) + pos_freq_terms = freq_domain[tuple(slices)] + slices[-1] = slice(1, -1) + neg_freq_terms = ivy.conj(pos_freq_terms[tuple(slices)][..., ::-1]) + combined_freq_terms = ivy.concat((pos_freq_terms, neg_freq_terms), axis=-1) + real_result = ivy.ifftn(combined_freq_terms, s=[size], axes=[-1], norm=norm) + real_result = ivy.moveaxis(real_result, -1, axis) + + if ivy.is_complex_dtype(x.dtype): + output_dtype = ivy.float32 if x.dtype == ivy.complex64 else ivy.float64 + else: + if str(x.dtype) in ["float64", "int64", "uint64"]: + output_dtype = ivy.float64 + else: + output_dtype = ivy.float32 + + result_t = ivy.astype(real_result, output_dtype) + return result_t + + @to_ivy_arrays_and_back @with_unsupported_dtypes({"1.25.2 and below": ("float16", "bfloat16")}, "numpy") def rfft(a, n=None, axis=-1, norm=None): 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 90a1a7449e765..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.20 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.20 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 c6d79f193d91d..3091b062ec1af 100644 --- a/ivy/functional/frontends/jax/numpy/logic.py +++ b/ivy/functional/frontends/jax/numpy/logic.py @@ -7,7 +7,10 @@ promote_types_of_jax_inputs as promote_jax_arrays, ) from ivy.utils.exceptions import IvyNotImplementedException -from ivy.func_wrapper import with_unsupported_dtypes +from ivy.func_wrapper import ( + with_supported_device_and_dtypes, + with_unsupported_dtypes, +) # --- Helpers --- # @@ -101,7 +104,7 @@ def equal(x1, x2, /): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.20 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 +288,7 @@ def right_shift(x1, x2, /): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.20 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) @@ -310,5 +313,40 @@ def setxor1d(ar1, ar2, assume_unique=False): return ret +@to_ivy_arrays_and_back +@with_supported_device_and_dtypes( + { + "0.4.30 and below": { + "cpu": ("uint8",), + }, + }, + "jax", +) +def unpackbits(x, /, *, axis=None, count=None, bitorder="big"): + x = ivy.asarray(x) + bits = ivy.asarray(1) << ivy.arange(8, dtype=ivy.uint8) + if bitorder == "big": + bits = bits[::-1] + if axis is None: + x = ivy.flatten(x) + axis = 0 + x = ivy.swapaxes(x, axis, -1) + + unpacked = ( + (x[..., None] & ivy.expand_dims(bits, axis=tuple(range(x.ndim)))) > 0 + ).astype(ivy.uint8) + remaining_dim_size = int(unpacked.shape.numel() / unpacked.shape[:-2].numel()) + unpacked = ivy.reshape(unpacked, tuple(unpacked.shape[:-2] + (remaining_dim_size,))) + if count is not None: + if count > unpacked.shape[-1]: + unpacked = ivy.pad( + unpacked, + [(0, 0)] * (unpacked.ndim - 1) + [(0, count - unpacked.shape[-1])], + ) + else: + unpacked = unpacked[..., :count] + return ivy.swapaxes(unpacked, axis, -1) + + alltrue = all sometrue = any diff --git a/ivy/functional/frontends/jax/numpy/manipulations.py b/ivy/functional/frontends/jax/numpy/manipulations.py index f3f3c1721c546..61fe0fe6279ff 100644 --- a/ivy/functional/frontends/jax/numpy/manipulations.py +++ b/ivy/functional/frontends/jax/numpy/manipulations.py @@ -331,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 1dc1f43e42fa8..e65900a59df0f 100644 --- a/ivy/functional/frontends/jax/numpy/mathematical_functions.py +++ b/ivy/functional/frontends/jax/numpy/mathematical_functions.py @@ -3,8 +3,9 @@ from ivy.functional.frontends.jax.func_wrapper import ( to_ivy_arrays_and_back, ) -from ivy.func_wrapper import with_unsupported_dtypes -from ivy.functional.frontends.jax.numpy import promote_types_of_jax_inputs +from ivy.func_wrapper import with_unsupported_dtypes, with_supported_dtypes +from ivy.functional.frontends.jax.lax import slice_in_dim +from ivy.functional.frontends.jax.numpy import promote_types_of_jax_inputs, concatenate from ivy.functional.frontends.numpy.manipulation_routines import trim_zeros from ivy.utils.einsum_path_helpers import ( parse_einsum_input, @@ -76,7 +77,7 @@ def around(a, decimals=0, out=None): @with_unsupported_dtypes( - {"0.4.20 and below": ("bfloat16",)}, + {"0.4.24 and below": ("bfloat16",)}, "jax", ) @to_ivy_arrays_and_back @@ -90,7 +91,7 @@ def ceil(x, /): return ivy.ceil(x) -@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 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 +182,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 +238,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,7 +316,7 @@ 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 = [], [], [], [] @@ -366,8 +367,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 +378,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 +421,7 @@ def expm1( @with_unsupported_dtypes( - {"0.4.20 and below": ("uint16",)}, + {"0.4.24 and below": ("uint16",)}, "jax", ) @to_ivy_arrays_and_back @@ -584,7 +585,7 @@ def minimum(x1, x2, /): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.20 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) @@ -626,7 +627,7 @@ def negative( @with_unsupported_dtypes( { - "0.4.20 and below": ( + "0.4.24 and below": ( "bfloat16", "float16", ) @@ -671,7 +672,7 @@ def polyadd(a1, a2): @with_unsupported_dtypes( - {"0.4.20 and below": ("float16",)}, + {"0.4.24 and below": ("float16",)}, "jax", ) @to_ivy_arrays_and_back @@ -713,7 +714,7 @@ def polydiv(u, v, *, trim_leading_zeros=False): @with_unsupported_dtypes( - {"0.4.20 and below": ("float16",)}, + {"0.4.24 and below": ("float16",)}, "jax", ) @to_ivy_arrays_and_back @@ -903,15 +904,51 @@ def trace(a, offset=0, axis1=0, axis2=1, out=None): @to_ivy_arrays_and_back -def trapz(y, x=None, dx=1.0, axis=-1, out=None): +def trapezoid(y, x=None, dx=1.0, axis=-1, out=None): return ivy.trapz(y, x=x, dx=dx, axis=axis, out=out) +def trapz(y, x=None, dx=1.0, axis=-1, out=None): + return trapezoid(y, x=x, dx=dx, axis=axis, out=out) + + @to_ivy_arrays_and_back def trunc(x): return ivy.trunc(x) +@with_supported_dtypes( + {"0.4.30 and below": ("float32", "float64", "int32", "int64")}, "jax" +) +@to_ivy_arrays_and_back +def unwrap(p, discont=None, axis=-1, period=2 * ivy.pi): + p = ivy.asarray(p) + _dtype_to_inexact = { + "int32": "float64", + "int64": "float64", + "float32": "float32", + "float64": "float64", + } + dtype = _dtype_to_inexact[p.dtype] + p = p.astype(dtype) + if discont is None: + discont = period / 2 + interval = period / 2 + dd = ivy.diff(p, axis=axis) + ddmod = ivy.remainder(dd + interval, period) - interval + ddmod = ivy.where((ddmod == -interval) & (dd > 0), interval, ddmod) + ph_correct = ivy.where(ivy.abs(dd) < discont, 0, ddmod - dd) + up = concatenate( + ( + slice_in_dim(p, 0, 1, axis=axis), + slice_in_dim(p, 1, None, axis=axis) + ivy.cumsum(ph_correct, axis=axis), + ), + axis=axis, + dtype=dtype, + ) + return up + + @to_ivy_arrays_and_back def vdot(a, b): a, b = promote_types_of_jax_inputs(a, b) diff --git a/ivy/functional/frontends/jax/numpy/searching_sorting.py b/ivy/functional/frontends/jax/numpy/searching_sorting.py index 3ad8b7b6d835f..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.20 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.20 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 bb40e941322a4..fa378e981e7bb 100644 --- a/ivy/functional/frontends/jax/numpy/statistical.py +++ b/ivy/functional/frontends/jax/numpy/statistical.py @@ -7,7 +7,6 @@ handle_jax_dtype, ) from ivy.functional.frontends.jax.numpy import promote_types_of_jax_inputs -from ivy.functional.backends.jax.experimental.elementwise import _normalize_axis_tuple @to_ivy_arrays_and_back @@ -103,7 +102,7 @@ def corrcoef(x, y=None, rowvar=True): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"0.4.20 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 +403,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): @@ -442,7 +443,7 @@ def _ureduce(a, func, keepdims=False, **kwargs): nd = a.ndim if axis is not None: - axis = _normalize_axis_tuple(axis, nd) + axis = ivy._normalize_axis_tuple(axis, nd) if keepdims: if out is not None: @@ -572,7 +573,7 @@ def ptp(a, axis=None, out=None, keepdims=False): @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"0.4.20 and below": ("complex64", "complex128", "bfloat16", "bool", "float16")}, + {"0.4.24 and below": ("complex64", "complex128", "bfloat16", "bool", "float16")}, "jax", ) def quantile( @@ -597,7 +598,7 @@ def quantile( @handle_jax_dtype -@with_unsupported_dtypes({"0.4.20 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 f8adcc6778a04..90bf3f6999ab8 100644 --- a/ivy/functional/frontends/jax/random.py +++ b/ivy/functional/frontends/jax/random.py @@ -30,7 +30,7 @@ def _remove_axis(shape, axis): @to_ivy_arrays_and_back -def PRNGKey(seed): +def PRNGKey(seed, *, impl=None): return ivy.array([0, seed % 4294967295 - (seed // 4294967295)], dtype=ivy.int64) @@ -38,7 +38,7 @@ def PRNGKey(seed): @to_ivy_arrays_and_back @with_supported_dtypes( { - "0.4.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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.20 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 92db96fb8a2d2..deffd6d14b6dc 100644 --- a/ivy/functional/frontends/mindspore/ops/function/nn_func.py +++ b/ivy/functional/frontends/mindspore/ops/function/nn_func.py @@ -105,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 @@ -149,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, ) @@ -218,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": ( @@ -345,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/numpy/__init__.py b/ivy/functional/frontends/numpy/__init__.py index 8d2eac7018fd3..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 diff --git a/ivy/functional/frontends/numpy/broadcast/methods.py b/ivy/functional/frontends/numpy/broadcast/methods.py index c029d51abdf3f..eeaf072c66f78 100644 --- a/ivy/functional/frontends/numpy/broadcast/methods.py +++ b/ivy/functional/frontends/numpy/broadcast/methods.py @@ -12,7 +12,7 @@ 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._data = (*zip(*(ivy.flatten(i) for i in data)),) self._iters = tuple(iter(ivy.flatten(i)) for i in data) @property 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/fft/discrete_fourier_transform.py b/ivy/functional/frontends/numpy/fft/discrete_fourier_transform.py index 609d4e303072b..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.2 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.2 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.2 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.2 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.2 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/linalg/norms_and_other_numbers.py b/ivy/functional/frontends/numpy/linalg/norms_and_other_numbers.py index e1d492dddfe2d..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.2 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.2 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 5aff9e9fa56f3..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.2 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.2 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.2 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.2 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.2 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 2eaf48cae2916..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 @@ -177,10 +179,12 @@ def _array_in_str(self): return masked_print_options return str(self._data.to_list()) if ivy.any(self._mask): - return str([ - masked_print_options if mask else x - for x, mask in zip(self._data.to_list(), self._mask.to_list()) - ]) + return str( + [ + masked_print_options if mask else x + for x, mask in zip(self._data.to_list(), self._mask.to_list()) + ] + ) return str(self._data.to_list()) @@ -192,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/arithmetic_operations.py b/ivy/functional/frontends/numpy/mathematical_functions/arithmetic_operations.py index 759e76272ca9a..ffe7dde3e21e2 100644 --- a/ivy/functional/frontends/numpy/mathematical_functions/arithmetic_operations.py +++ b/ivy/functional/frontends/numpy/mathematical_functions/arithmetic_operations.py @@ -91,10 +91,12 @@ def _divmod( ret = ivy.where( where, ret, - ([ - ivy.default(out, ivy.zeros_like(ret[0])), - ivy.default(out, ivy.zeros_like(ret[1])), - ]), + ( + [ + ivy.default(out, ivy.zeros_like(ret[0])), + ivy.default(out, ivy.zeros_like(ret[1])), + ] + ), out=out, ) return ret 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/miscellaneous.py b/ivy/functional/frontends/numpy/mathematical_functions/miscellaneous.py index 43da4792f5f9d..c93e71243ae57 100644 --- a/ivy/functional/frontends/numpy/mathematical_functions/miscellaneous.py +++ b/ivy/functional/frontends/numpy/mathematical_functions/miscellaneous.py @@ -9,7 +9,9 @@ from_zero_dim_arrays_to_scalar, handle_numpy_out, ) -from ivy.func_wrapper import with_supported_dtypes + + +from ivy.func_wrapper import with_supported_dtypes, with_unsupported_dtypes # --- Helpers --- # @@ -147,7 +149,7 @@ def _fabs( @to_ivy_arrays_and_back @from_zero_dim_arrays_to_scalar @with_supported_dtypes( - {"1.26.2 and below": ("int8", "int16", "int32", "int64")}, "numpy" + {"1.26.3 and below": ("int8", "int16", "int32", "int64")}, "numpy" ) # Add def _gcd( x1, @@ -331,6 +333,13 @@ def convolve(a, v, mode="full"): return result[0, 0, out_order] +@with_unsupported_dtypes({"2.0.1 and below": ("bfloat16",)}, "numpy") +@to_ivy_arrays_and_back +def gradient(f, *varargs, axis=None, edge_order=None): + edge_order = edge_order if edge_order is not None else 1 + return ivy.gradient(f, spacing=varargs, axis=axis, edge_order=edge_order) + + @to_ivy_arrays_and_back @from_zero_dim_arrays_to_scalar def interp(x, xp, fp, left=None, right=None, period=None): diff --git a/ivy/functional/frontends/numpy/ndarray/ndarray.py b/ivy/functional/frontends/numpy/ndarray/ndarray.py index 31ff643ec4888..fcb9e0e6684ed 100644 --- a/ivy/functional/frontends/numpy/ndarray/ndarray.py +++ b/ivy/functional/frontends/numpy/ndarray/ndarray.py @@ -329,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) @@ -415,7 +415,7 @@ def tolist(self) -> list: @with_supported_device_and_dtypes( { - "1.26.2 and below": { + "1.26.3 and below": { "cpu": ( "int64", "float32", @@ -732,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/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 fb0795ec8750c..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.2 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 1484182c4f62a..d17d4785ef9ab 100644 --- a/ivy/functional/frontends/numpy/statistics/order_statistics.py +++ b/ivy/functional/frontends/numpy/statistics/order_statistics.py @@ -1,5 +1,6 @@ # global import ivy +from ivy.func_wrapper import with_unsupported_dtypes from ivy.functional.frontends.numpy.func_wrapper import ( to_ivy_arrays_and_back, handle_numpy_out, @@ -11,8 +12,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. @@ -120,6 +120,7 @@ def nanpercentile( @to_ivy_arrays_and_back @handle_numpy_out +@with_unsupported_dtypes({"1.26.4 and below": ("bool",)}, "numpy") def ptp(a, axis=None, out=None, keepdims=False): x = ivy.max(a, axis=axis, keepdims=keepdims) y = ivy.min(a, axis=axis, keepdims=keepdims) diff --git a/ivy/functional/frontends/numpy/ufunc/methods.py b/ivy/functional/frontends/numpy/ufunc/methods.py index 0a4a9c5bfb5c1..5d35a7a8a2448 100644 --- a/ivy/functional/frontends/numpy/ufunc/methods.py +++ b/ivy/functional/frontends/numpy/ufunc/methods.py @@ -214,20 +214,24 @@ def __init__(self, name) -> None: @property def nargs(self): sig = inspect.signature(self.func) - return len([ - param - for param in sig.parameters.values() - if param.kind in [param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD] - ]) + return len( + [ + param + for param in sig.parameters.values() + if param.kind in [param.POSITIONAL_ONLY, param.POSITIONAL_OR_KEYWORD] + ] + ) @property def nin(self): sig = inspect.signature(self.func) - return len([ - param - for param in sig.parameters.values() - if param.kind == param.POSITIONAL_ONLY - ]) + return len( + [ + param + for param in sig.parameters.values() + if param.kind == param.POSITIONAL_ONLY + ] + ) @property def nout(self): 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 24d90399e4f8a..8ac3f6dd1b6ee 100644 --- a/ivy/functional/frontends/paddle/creation.py +++ b/ivy/functional/frontends/paddle/creation.py @@ -7,30 +7,26 @@ ) -@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 arange(start, end=None, step=1, dtype=None, name=None): return ivy.arange(start, end, step=step, dtype=dtype) @with_supported_dtypes( - {"2.5.2 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 def assign(x, output=None): - if len(ivy.shape(x)) == 0: - x = ivy.reshape(ivy.Array(x), (1,)) - if ivy.exists(output): - output = ivy.reshape(ivy.Array(output), (1,)) - else: + if len(ivy.shape(x)) != 0: x = ivy.reshape(x, ivy.shape(x)) ret = ivy.copy_array(x, to_ivy_array=False, out=output) return ret @with_unsupported_dtypes( - {"2.5.2 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 +34,7 @@ def clone(x): @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64")}, + {"2.6.0 and below": ("float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -54,7 +50,7 @@ def complex(real, imag, name=None): @with_supported_dtypes( - {"2.5.2 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 +65,7 @@ def diag(x, offset=0, padding_value=0, name=None): @with_supported_dtypes( - {"2.5.2 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 +83,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 +104,7 @@ def full_like(x, fill_value, /, *, dtype=None, name=None): @with_supported_dtypes( - {"2.5.2 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 +112,7 @@ def linspace(start, stop, num, dtype=None, name=None): @with_supported_dtypes( - {"2.5.2 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 +120,14 @@ def logspace(start, stop, num, base=10.0, dtype=None, name=None): @with_supported_dtypes( - {"2.5.2 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.2 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 +135,7 @@ def ones(shape, /, *, dtype=None, name=None): @with_unsupported_dtypes( - {"2.5.2 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): @@ -150,16 +149,16 @@ def to_tensor(data, /, *, dtype=None, place=None, stop_gradient=True): return paddle_frontend.Tensor(array, dtype=dtype, place=place) -@with_unsupported_dtypes( +@with_supported_dtypes( { - "2.5.2 and below": ( - "uint8", - "int8", - "int16", - "float16", + "2.6.0 and below": ( + "bool", + "float64", + "float32", + "int32", + "int64", "complex64", "complex128", - "bool", ) }, "paddle", @@ -169,7 +168,7 @@ def tril(x, diagonal=0, name=None): return ivy.tril(x, k=diagonal) -@with_supported_dtypes({"2.5.2 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) @@ -177,16 +176,15 @@ def tril_indices(row, col, offset=0, dtype="int64"): return arr -@with_unsupported_dtypes( +@with_supported_dtypes( { - "2.5.2 and below": ( - "uint8", - "int8", - "int16", - "float16", + "2.6.0 and below": ( + "float64", + "float32", + "int32", + "int64", "complex64", "complex128", - "bool", ) }, "paddle", @@ -196,7 +194,7 @@ def triu(x, diagonal=0, name=None): return ivy.triu(x, k=diagonal) -@with_supported_dtypes({"2.5.2 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 +204,7 @@ def triu_indices(row, col=None, offset=0, dtype="int64"): return arr -@with_unsupported_dtypes({"2.5.2 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 +212,7 @@ def zeros(shape, /, *, dtype=None, name=None): @with_unsupported_dtypes( - {"2.5.2 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 75f3f089cdd58..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.2 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -18,7 +18,7 @@ def fft(x, n=None, axis=-1.0, norm="backward", name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -37,7 +37,7 @@ def fft2(x, s=None, axes=(-2, -1), norm="backward", name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -63,7 +63,7 @@ def fftfreq(n, d=1.0, dtype=None, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -92,13 +92,13 @@ def fftshift(x, axes=None, name=None): @with_supported_dtypes( - {"2.5.2 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] @@ -114,7 +114,7 @@ def hfft(x, n=None, axes=-1, norm="backward", name=None): @with_supported_dtypes( - {"2.5.2 and below": "complex64"}, + {"2.6.0 and below": "complex64"}, "paddle", ) @to_ivy_arrays_and_back @@ -135,7 +135,7 @@ def hfft2(x, s=None, axis=(-2, -1), norm="backward"): @with_supported_dtypes( - {"2.5.2 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -145,7 +145,7 @@ def ifft(x, n=None, axis=-1.0, norm="backward", name=None): @with_supported_dtypes( - {"2.5.2 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -156,7 +156,7 @@ def ifftn(x, s=None, axes=None, norm="backward", name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -184,7 +184,7 @@ def ifftshift(x, axes=None, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -217,8 +217,28 @@ def ihfft2(x, s=None, axes=(-2, -1), norm="backward", name=None): 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.2 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -237,7 +257,7 @@ def irfft(x, n=None, axis=-1.0, norm="backward", name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float16", @@ -260,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": @@ -273,7 +293,7 @@ def irfft2(x, s=None, axes=(-2, -1), norm="backward"): @with_supported_dtypes( - {"2.5.2 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -324,7 +344,7 @@ def irfftn(x, s=None, axes=None, norm="backward", name=None): return result_t -@with_supported_dtypes({"2.5.2 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 23d7e51f918de..0b9f1a511e327 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.2 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.2 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.2 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.2 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) @@ -50,8 +50,17 @@ def cond(x, p=None, name=None): return ret +# cov @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.1 and below": ("complex64", "complex128", "float32", "float64")}, "paddle" +) +@to_ivy_arrays_and_back +def cov(x, rowvar=True, ddof=True, fweights=None, aweights=None, name=None): + return ivy.cov(x, rowVar=rowvar, ddof=ddof, fweights=fweights, aweights=aweights) + + +@with_supported_dtypes( + {"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 +71,7 @@ def cross(x, y, /, *, axis=9, name=None): # diagonal @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float64", @@ -87,7 +96,7 @@ def dist(x, y, p=2): # dot -@with_supported_dtypes({"2.5.2 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 +160,7 @@ def lu_unpack(lu_data, lu_pivots, unpack_datas=True, unpack_pivots=True, *, out= # matmul -@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 matmul(x, y, transpose_x=False, transpose_y=False, name=None): x, y = promote_types_of_paddle_inputs(x, y) @@ -159,21 +168,21 @@ def matmul(x, y, transpose_x=False, transpose_y=False, name=None): # matrix_power -@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 matrix_power(x, n, name=None): return ivy.matrix_power(x, n) # mv -@with_supported_dtypes({"2.5.2 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.2 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: @@ -226,7 +235,7 @@ def norm(x, p="fro", axis=None, keepdim=False, name=None): # pinv -@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 pinv(x, rcond=1e-15, hermitian=False, name=None): # TODO: Add hermitian functionality @@ -234,21 +243,21 @@ def pinv(x, rcond=1e-15, hermitian=False, name=None): # qr -@with_supported_dtypes({"2.5.2 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.2 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.2 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 220d26ded9aaf..b19a416465794 100644 --- a/ivy/functional/frontends/paddle/logic.py +++ b/ivy/functional/frontends/paddle/logic.py @@ -13,7 +13,7 @@ @with_supported_dtypes( { - "2.5.2 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.2 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.2 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.2 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.2 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -110,7 +110,7 @@ def bitwise_xor(x, y, /, *, name=None, out=None): @with_unsupported_dtypes( - {"2.5.2 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, + {"2.6.0 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -120,24 +120,25 @@ def equal(x, y, /, *, name=None): @with_unsupported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", "float16", "complex64", "complex128", + "bfloat16", ) }, "paddle", ) @to_ivy_arrays_and_back def equal_all(x, y, /, *, name=None): - return paddle.to_tensor([ivy.array_equal(x, y)]) + return ivy.all_equal(x, y) @with_unsupported_dtypes( - {"2.5.2 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 @@ -146,7 +147,7 @@ def greater_equal(x, y, /, *, name=None): @with_unsupported_dtypes( - {"2.5.2 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 @@ -155,12 +156,26 @@ def greater_than(x, y, /, *, name=None): @with_unsupported_dtypes( - {"2.5.2 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, + { + "2.6.0 and below": ( + "uint8", + "int8", + "int16", + "complex64", + "complex128", + "bool", + "float16", + "bfloat16", + ) + }, "paddle", ) @to_ivy_arrays_and_back def is_empty(x, name=None): - return ivy.is_empty(x) + if 0 in ivy.shape(x): + return ivy.array(True) + else: + return ivy.array(False) @to_ivy_arrays_and_back @@ -170,7 +185,7 @@ def is_tensor(x): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "float32", "float64", ) @@ -183,7 +198,7 @@ def isclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name=None): @with_unsupported_dtypes( - {"2.5.2 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 @@ -192,7 +207,7 @@ def less_equal(x, y, /, *, name=None): @with_supported_dtypes( - {"2.5.2 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 @@ -202,7 +217,7 @@ def less_than(x, y, /, *, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -222,7 +237,7 @@ def logical_and(x, y, /, *, name=None, out=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -242,7 +257,7 @@ def logical_not(x, /, *, name=None, out=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -262,7 +277,7 @@ def logical_or(x, y, /, *, name=None, out=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -281,7 +296,7 @@ def logical_xor(x, y, /, *, name=None, out=None): @with_unsupported_dtypes( - {"2.5.2 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, + {"2.6.0 and below": ("uint8", "int8", "int16", "complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/paddle/manipulation.py b/ivy/functional/frontends/paddle/manipulation.py index 69e9f6c22dbb3..fb486570f5adc 100644 --- a/ivy/functional/frontends/paddle/manipulation.py +++ b/ivy/functional/frontends/paddle/manipulation.py @@ -10,14 +10,14 @@ ) -@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 abs(x, name=None): return ivy.abs(x) @with_supported_dtypes( - {"2.5.2 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.2 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.2 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.2 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.2 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.2 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.2 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,47 @@ 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 + + +@with_supported_dtypes({"2.5.1 and below": ("int32", "int64")}, "paddle") +@to_ivy_arrays_and_back +def one_hot(x, num_classes, name=None): + if not isinstance(num_classes, int) or num_classes <= 0: + raise ValueError("num_classes must be a positive integer.") + + one_hot_tensor = ivy.one_hot(x, num_classes) + return one_hot_tensor.astype(ivy.float32) + + @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 +134,7 @@ def put_along_axis(arr, indices, values, axis, reduce="assign"): @with_supported_dtypes( - {"2.5.2 and below": ("int32", "int64", "float32", "float64")}, + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back @@ -126,7 +167,7 @@ def roll(x, shifts, axis=None, name=None): @with_supported_device_and_dtypes( { - "2.5.2 and above": { + "2.6.0 and above": { "cpu": ( "bool", "int32", @@ -145,7 +186,7 @@ def rot90(x, k=1, axes=(0, 1), name=None): @with_unsupported_dtypes( - {"2.5.2 and below": ("int16", "complex64", "complex128")}, + {"2.6.0 and below": ("int16", "complex64", "complex128")}, "paddle", ) @to_ivy_arrays_and_back @@ -154,7 +195,7 @@ def split(x, num_or_sections, axis=0, name=None): @with_unsupported_dtypes( - {"2.5.2 and below": ("float16", "bfloat16", "int8", "int16")}, + {"2.6.0 and below": ("float16", "bfloat16", "int8", "int16")}, "paddle", ) @to_ivy_arrays_and_back @@ -167,12 +208,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.2 and below": ("int8", "uint8", "int16", "float16")}, + {"2.6.0 and below": ("int8", "uint8", "int16", "float16", "bfloat16")}, "paddle", ) @to_ivy_arrays_and_back @@ -186,7 +232,7 @@ def tolist(x): @with_supported_dtypes( - {"2.5.2 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 @@ -198,7 +244,7 @@ def unbind(input, axis=0): @with_supported_dtypes( - {"2.5.2 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 +254,7 @@ def unique_consecutive(x, axis=0): @with_supported_dtypes( { - "2.5.2 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 f8cd603766781..016309f169fe0 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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,44 +122,56 @@ def atan2(x, y, name=None): return ivy.atan2(x, y) -@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 atanh(x, name=None): return ivy.atanh(x) -@with_supported_dtypes({"2.5.2 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.2 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) -@with_unsupported_dtypes({"2.4.2 and below": ("int16", "float16")}, "paddle") +@with_supported_dtypes( + { + "2.6.0 and below": ( + "complex64", + "complex128", + "float32", + "float64", + "int32", + "int64", + ) + }, + "paddle", +) @to_ivy_arrays_and_back def conj(x, name=None): return ivy.conj(x) -@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 cos(x, name=None): return ivy.cos(x) -@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 cosh(x, name=None): return ivy.cosh(x) @with_supported_dtypes( - {"2.5.2 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 +181,7 @@ def count_nonzero(x, axis=None, keepdim=False, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float32", @@ -186,14 +198,14 @@ def cumprod(x, dim=None, dtype=None, name=None): @with_supported_dtypes( - {"2.5.2 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.2 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 +213,7 @@ def deg2rad(x, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float64", @@ -219,53 +231,51 @@ def diagonal(x, offset=0, axis1=0, axis2=1, name=None): @with_supported_dtypes( - {"2.5.2 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.2 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.2 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.2 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.2 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.2 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.2 and below": ("bfloat16", "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.floor(x) -@with_supported_dtypes({"2.5.2 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) @@ -273,7 +283,7 @@ def floor_divide(x, y, name=None): @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64", "int32", "int64"), "gpu": ("float16", "float32", "float64", "int32", "int64"), } @@ -285,20 +295,24 @@ def floor_mod(x, y, name=None): return ivy.remainder(x, y) -@with_unsupported_dtypes({"2.5.2 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.2 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.2 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): @@ -306,21 +320,21 @@ def frac(x, name=None): return ivy.subtract(x, y) -@with_supported_dtypes({"2.5.2 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.2 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("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.2 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) @@ -331,14 +345,14 @@ def inner(x, y, name=None): return result -@with_supported_dtypes({"2.5.2 and below": ("float32", "float64")}, "paddle") +@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.2 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): @@ -346,7 +360,7 @@ def isfinite(x, name=None): @with_supported_dtypes( - {"2.5.2 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): @@ -354,7 +368,7 @@ def isinf(x, name=None): @with_supported_dtypes( - {"2.5.2 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): @@ -362,63 +376,86 @@ def isnan(x, name=None): @with_supported_dtypes( - {"2.5.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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): @@ -426,14 +463,14 @@ def max(x, axis=None, keepdim=False, name=None): # maximum -@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 maximum(x, y, name=None): return ivy.maximum(x, y) @with_supported_dtypes( - {"2.5.2 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): @@ -441,7 +478,7 @@ def min(x, axis=None, keepdim=False, name=None): @with_supported_dtypes( - {"2.5.2 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): @@ -449,27 +486,27 @@ def minimum(x, y, name=None): @with_supported_dtypes( - {"2.5.2 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.2 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.2 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.2 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): @@ -477,7 +514,7 @@ def nansum(x, axis=None, dtype=None, name=None): @with_supported_dtypes( - {"2.5.2 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 @@ -485,39 +522,41 @@ def neg(x, name=None): return ivy.negative(x) -@with_supported_dtypes({"2.5.2 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.2 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.2 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.2 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.2 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.2 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) @@ -525,7 +564,7 @@ def remainder(x, y, name=None): @with_supported_device_and_dtypes( { - "2.5.2 and below": { + "2.6.0 and below": { "cpu": ("float32", "float64"), "gpu": ("float16", "float32", "float64"), } @@ -537,7 +576,7 @@ def remainder_(x, y, name=None): return ivy.inplace_update(x, remainder(x, y)) -@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 round(x, name=None): sign = ivy.sign(x) @@ -545,61 +584,56 @@ def round(x, name=None): return x -@with_supported_dtypes({"2.5.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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 - exp_ax = ivy.exp(ivy.multiply(scale_a, x)) - exp_minus_ax = ivy.exp(ivy.multiply(-scale_a, x)) - numerator = ivy.subtract(exp_ax, exp_minus_ax) - denominator = ivy.add(exp_ax, exp_minus_ax) - ret = ivy.multiply(scale_b, ivy.divide(numerator, denominator)) - return ret + ret = ivy.stanh(x, alpha=scale_b, beta=scale_a, out=name) + return ivy.asarray(ret, dtype=x.dtype) -@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 subtract(x, y, name=None): return ivy.subtract(x, y) @@ -607,7 +641,7 @@ def subtract(x, y, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "float64", "int64", ) @@ -625,7 +659,7 @@ def sum(x, axis=None, dtype=None, keepdim=False, name=None): @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "int32", "int6")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int6")}, "paddle" ) @to_ivy_arrays_and_back def take( @@ -647,20 +681,20 @@ def take( return ivy.gather(x, index, axis=0) -@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 tan(x, name=None): return ivy.tan(x) -@with_supported_dtypes({"2.5.2 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.2 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): @@ -668,11 +702,11 @@ def trace(x, offset=0, axis1=0, axis2=1, name=None): @with_supported_dtypes( - {"2.4.2 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle" ) @to_ivy_arrays_and_back -def trunc(x, name=None): - return ivy.trunc(x) +def trunc(input, name=None): + return ivy.trunc(input) mod = remainder diff --git a/ivy/functional/frontends/paddle/nn/functional/activation.py b/ivy/functional/frontends/paddle/nn/functional/activation.py index f8621b7f3f998..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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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 ef27e44b2fa41..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.2 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.2 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.2 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, training=training, data_format=data_format) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.2 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.2 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.2 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.2 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.2 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 296ba22e4237c..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.2 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.2 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.2 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.2 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.2 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.2 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 52d07db32110b..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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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 17e2aca071c79..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.2 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.2 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 910946dfbaf6e..219b73f8a47b7 100644 --- a/ivy/functional/frontends/paddle/nn/functional/pooling.py +++ b/ivy/functional/frontends/paddle/nn/functional/pooling.py @@ -7,15 +7,15 @@ @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.2 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.2 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 @@ -25,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.2 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.2 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 ): @@ -61,7 +61,7 @@ def avg_pool1d( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.2 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def avg_pool2d( x, kernel_size, @@ -99,7 +99,7 @@ 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, @@ -118,8 +118,7 @@ def max_pool2d( if data_format not in ["NCHW", "NHWC"]: raise ValueError( "Attr(data_format) should be 'NCHW' or 'NHWC'. Received " - "Attr(data_format): %s." - % str(data_format) + f"Attr(data_format): {data_format}." ) if data_format == "NHWC" and return_mask: @@ -134,7 +133,7 @@ def max_pool2d( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.2 and below": ("float32", "float64")}, "paddle") +@with_supported_dtypes({"2.6.0 and below": ("float32", "float64")}, "paddle") def max_unpool1d( x, indices, diff --git a/ivy/functional/frontends/paddle/nn/functional/vision.py b/ivy/functional/frontends/paddle/nn/functional/vision.py index 5f25344dd0a34..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.2 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 @@ -18,9 +18,9 @@ def affine_grid(theta, out_shape, align_corners=True): base_grid[:, :, :, 0] = ivy.linspace(-1, 1, W) base_grid[:, :, :, 1] = ivy.expand_dims(ivy.linspace(-1, 1, H), axis=-1) height_values = ivy.expand_dims(ivy.linspace(-1, 1, H), axis=-1) - base_grid[:, :, :, 1] = ivy.array([ - [[height_values[i]] * W for i in range(H)] - ])[:, :, :, 0] + base_grid[:, :, :, 1] = ivy.array( + [[[height_values[i]] * W for i in range(H)]] + )[:, :, :, 0] base_grid[:, :, :, 2] = ivy.full((H, W), 1) grid = ivy.matmul(base_grid.view((N, H * W, 3)), theta.swapaxes(1, 2)) return grid.view((N, H, W, 2)) @@ -32,9 +32,9 @@ def affine_grid(theta, out_shape, align_corners=True): height_values = ivy.expand_dims( ivy.linspace(-1, 1, H) * (H - 1) / H, axis=-1 ) - base_grid[:, :, :, 1] = ivy.array([ - [[height_values[i]] * W for i in range(H)] - ])[:, :, :, 0] + base_grid[:, :, :, 1] = ivy.array( + [[[height_values[i]] * W for i in range(H)]] + )[:, :, :, 0] base_grid[:, :, :, 2] = ivy.full((H, W), 1) grid = ivy.matmul(base_grid.view((N, H * W, 3)), ivy.swapaxes(theta, 1, 2)) return grid.view((N, H, W, 2)) @@ -45,9 +45,9 @@ def affine_grid(theta, out_shape, align_corners=True): base_grid[:, :, :, :, 0] = ivy.linspace(-1, 1, W) base_grid[:, :, :, :, 1] = ivy.expand_dims(ivy.linspace(-1, 1, H), axis=-1) height_values = ivy.linspace(-1, 1, H) - base_grid[:, :, :, :, 1] = ivy.array([ - [[[height_values[i]] * W for i in range(H)]] * D - ]) + base_grid[:, :, :, :, 1] = ivy.array( + [[[[height_values[i]] * W for i in range(H)]] * D] + ) base_grid[:, :, :, :, 2] = ivy.expand_dims( ivy.expand_dims(ivy.linspace(-1, 1, D), axis=-1), axis=-1 ) @@ -58,24 +58,24 @@ def affine_grid(theta, out_shape, align_corners=True): ivy.linspace(-1, 1, H) * (H - 1) / H, axis=-1 ) height_values = ivy.linspace(-1, 1, H) * (H - 1) / H - base_grid[:, :, :, :, 1] = ivy.array([ - [[[height_values[i]] * W for i in range(H)]] * D - ]) + base_grid[:, :, :, :, 1] = ivy.array( + [[[[height_values[i]] * W for i in range(H)]] * D] + ) base_grid[:, :, :, :, 2] = ivy.expand_dims( ivy.expand_dims(ivy.linspace(-1, 1, D) * (D - 1) / D, axis=-1), axis=-1 ) width_values = ivy.linspace(-1, 1, D) * (D - 1) / D - base_grid[:, :, :, :, 2] = ivy.array([ - [ivy.array([[width_values[i]] * W] * H) for i in range(D)] - ]) + base_grid[:, :, :, :, 2] = ivy.array( + [[ivy.array([[width_values[i]] * W] * H) for i in range(D)]] + ) base_grid[:, :, :, :, 3] = ivy.full((D, H, W), 1) grid = ivy.matmul(base_grid.view((N, D * H * W, 4)), theta.swapaxes(1, 2)) return grid.view((N, D, H, W, 3)) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.5.2 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 2a436935b9933..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.2 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.2 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.2 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.2 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.2 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.2 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.2 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 c26923d08ae2e..4199a36d950e0 100644 --- a/ivy/functional/frontends/paddle/search.py +++ b/ivy/functional/frontends/paddle/search.py @@ -7,7 +7,7 @@ @with_supported_dtypes( - {"2.5.2 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.2 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 @@ -25,7 +25,7 @@ def argmin(x, /, *, axis=None, keepdim=False, dtype="int64", name=None): @with_supported_dtypes( - {"2.4.2 and below": ("float32", "float64", "int16", "int32", "int64", "uint8")}, + {"2.4.2 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -34,17 +34,19 @@ def argsort(x, /, *, axis=-1, descending=False, name=None): @with_supported_dtypes( - {"2.5.2 and below": ("int32", "int64", "float32", "float64")}, + {"2.6.0 and below": ("int32", "int64", "float32", "float64")}, "paddle", ) @to_ivy_arrays_and_back def index_sample(x, index): - return x[ivy.arange(x.shape[0])[:, None], index] + index_dtype = index.dtype + arange_tensor = ivy.arange(x.shape[0], dtype=index_dtype)[:, None] + return x[arange_tensor, index] # kthvalue @with_supported_dtypes( - {"2.5.2 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 +67,7 @@ def kthvalue(x, k, axis=None, keepdim=False, name=None): @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -86,7 +88,7 @@ def nonzero(input, /, *, as_tuple=False): @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -102,7 +104,7 @@ def searchsorted(sorted_sequence, values, out_int32=False, right=False, name=Non @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -111,7 +113,7 @@ def sort(x, /, *, axis=-1, descending=False, name=None): @with_supported_dtypes( - {"2.5.2 and below": ("float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float32", "float64", "int32", "int64")}, "paddle", ) @to_ivy_arrays_and_back @@ -121,7 +123,7 @@ def topk(x, k, axis=None, largest=True, sorted=True, name=None): # where @with_supported_dtypes( - {"2.5.2 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 1ee6edd5ce54d..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.2 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.2 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.2 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.2 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.2 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 5300c5ba213d9..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.2 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 ceb36b11d7310..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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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 dd6be26c2f4f2..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.2 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.2 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 be368a3ca9617..c93302a1a9bee 100644 --- a/ivy/functional/frontends/paddle/tensor/tensor.py +++ b/ivy/functional/frontends/paddle/tensor/tensor.py @@ -62,28 +62,28 @@ def ivy_array(self, array): # -------------------# @with_unsupported_dtypes( - {"2.5.2 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.5.2 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + {"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.5.2 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + {"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.5.2 and below": ("uint8", "int8", "int16", "float16", "bfloat16")}, + {"2.6.0 and below": ("uint8", "int8", "int16", "float16", "bfloat16")}, "paddle", ) def __mul__(self, y, /, name=None): @@ -91,7 +91,7 @@ def __mul__(self, y, /, name=None): @with_unsupported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -107,7 +107,23 @@ def __gt__(self, y, /, name=None): @with_unsupported_dtypes( { - "2.5.2 and below": ( + "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", @@ -123,7 +139,7 @@ def __ge__(self, y, /, name=None): @with_unsupported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -139,7 +155,7 @@ def __le__(self, y, /, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -154,7 +170,7 @@ def __or__(self, y, /, name=None): return paddle_frontend.logic.bitwise_or(self, y) @with_unsupported_dtypes( - {"2.5.2 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, "paddle", ) def __rsub__(self, x, /, name=None): @@ -170,11 +186,11 @@ def __setitem__(self, item, value): "ivy.functional.frontends.paddle.Tensor object doesn't support assignment" ) - @with_unsupported_dtypes({"2.5.2 and below": ("float16", "bfloat16")}, "paddle") + @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.5.2 and below": ("float16", "bfloat16")}, "paddle") + @with_unsupported_dtypes({"2.6.0 and below": ("float16", "bfloat16")}, "paddle") def __ne__(self, y, /, name=None): return paddle_frontend.not_equal(self, y) @@ -185,14 +201,14 @@ def __iter__(self): yield self[i] @with_unsupported_dtypes( - {"2.5.2 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + {"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.5.2 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + {"2.6.0 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, "paddle", ) def __float__(self): @@ -201,6 +217,9 @@ def __float__(self): 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) @@ -208,14 +227,21 @@ def __neg__(self): return paddle_frontend.neg(self) @with_unsupported_dtypes( - {"2.5.2 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + {"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.5.2 and below": ("bool", "unsigned", "int8", "float16", "bfloat16")}, + {"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): @@ -226,7 +252,28 @@ def __int__(self): "paddle", ) def __div__(self, y, name=None): - return paddle_frontend.math.divide(self, y, name=name) + return paddle_frontend.divide(self, y, name=name) + + @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 # # ---------------- # @@ -245,50 +292,73 @@ def reshape(self, *args, shape=None): 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 and below": ( + "2.6.0 and below": ( "int32", "int64", "float64", @@ -303,101 +373,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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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( @@ -417,85 +487,106 @@ def clip(self, min=None, max=None, name=None): return paddle_frontend.Tensor(ret) @with_supported_dtypes( - {"2.5.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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) @@ -517,7 +608,7 @@ def bitwise_and(self, y, out=None, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -533,22 +624,22 @@ def logical_or(self, y, out=None, name=None): return paddle_frontend.logical_or(self, y, out=out) @with_supported_dtypes( - {"2.5.2 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.2 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.2 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.2 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): @@ -556,7 +647,7 @@ def bitwise_not(self, out=None, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -571,7 +662,7 @@ def bitwise_or(self, y, out=None, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -587,7 +678,7 @@ def logical_xor(self, y, out=None, name=None): return paddle_frontend.logical_xor(self, y, out=out) @with_supported_dtypes( - {"2.5.2 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle", ) def isnan(self, name=None): @@ -595,7 +686,7 @@ def isnan(self, name=None): @with_unsupported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -609,22 +700,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.2 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.2 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.2 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.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -639,12 +730,12 @@ 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.2 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.2 and below": ("float32", "float64", "complex64", "complex128")}, + {"2.6.0 and below": ("float32", "float64", "complex64", "complex128")}, "paddle", ) def eigvals(self, name=None): @@ -652,7 +743,7 @@ def eigvals(self, name=None): @with_unsupported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "uint8", "int8", @@ -666,18 +757,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.2 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.2 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.2 and below": ("complex64", "complex128", "float32", "float64")}, + {"2.6.0 and below": ("complex64", "complex128", "float32", "float64")}, "paddle", ) def angle(self, name=None): @@ -685,7 +776,7 @@ def angle(self, name=None): @with_unsupported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", @@ -698,13 +789,13 @@ def angle(self, name=None): def equal(self, y, name=None): return paddle_frontend.equal(self, y) - @with_unsupported_dtypes({"2.5.2 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.2 and below": ( + "2.6.0 and below": ( "uint8", "int8", "int16", @@ -718,46 +809,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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 and below": ("complex64", "complex128")}, + {"2.6.0 and below": ("complex64", "complex128")}, "paddle", ) def imag(self, name=None): @@ -768,7 +859,7 @@ def is_tensor(self): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "float32", "float64", ) @@ -780,16 +871,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.2 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.2 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.2 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) @@ -797,7 +894,7 @@ def cond(self, p=None, name=None): def conj(self, name=None): return paddle_frontend.conj(self) - @with_supported_dtypes({"2.5.2 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) @@ -809,7 +906,7 @@ def neg(self, name=None): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int8", "int16", @@ -824,15 +921,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.2 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.2 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.2 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) @@ -840,45 +937,45 @@ def tolist(self): return paddle_frontend.Tensor(ivy.to_list(self._ivy_array)) @with_supported_dtypes( - {"2.5.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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( @@ -888,21 +985,55 @@ 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.2 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.2 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.2 and below": ( + "2.6.0 and below": ( "float32", "float64", "int16", @@ -917,48 +1048,52 @@ 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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.2 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( @@ -973,29 +1108,29 @@ def as_complex(self, name=None): return value @with_supported_dtypes( - {"2.5.2 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.2 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.2 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.2 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.2 and below": ( + "2.6.0 and below": ( "bool", "float16", "float32", @@ -1010,12 +1145,12 @@ def t(self, name=None): def cast(self, dtype): return paddle_frontend.cast(self, dtype) - @with_unsupported_dtypes({"2.5.2 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.2 and below": ("float16", "float32", "float64", "int32", "int64")}, + {"2.6.0 and below": ("float16", "float32", "float64", "int32", "int64")}, "paddle", ) def fill_(self, value): @@ -1024,7 +1159,7 @@ def fill_(self, value): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int32", "int64", @@ -1040,7 +1175,7 @@ def unbind(self, axis=0): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "int32", "int64", @@ -1059,19 +1194,19 @@ def cpu(self): return self @with_unsupported_dtypes( - {"2.5.2 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.2 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.2 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) @@ -1079,27 +1214,27 @@ def is_complex(self): return paddle_frontend.is_complex(self) @with_unsupported_dtypes( - {"2.5.2 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.5.2 and below": ("float32", "float64", "int32", "int64")}, "paddle" + {"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.5.2 and below": ("bool", "int32", "int64", "float32", "float64")}, "paddle" + {"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.2 and below": { + "2.6.0 and below": { "cpu": ( "bool", "int32", @@ -1118,7 +1253,7 @@ def tile(self, repeat_times): @with_supported_dtypes( { - "2.5.2 and below": ( + "2.6.0 and below": ( "bool", "float16", "float32", diff --git a/ivy/functional/frontends/paddle/vision/transforms.py b/ivy/functional/frontends/paddle/vision/transforms.py index dac89b602ea19..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.2 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.2 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.2 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.2 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.2 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.2 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.2 and below": { + "2.6.0 and below": { "cpu": ("int8", "uint8", "int16", "float16", "bfloat16", "bool") } }, 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/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..0ad23d568cc41 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,147 @@ 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 f1_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, predicted positives, and actual positives + true_positives = ivy.logical_and(ivy.equal(y_true, 1), ivy.equal(y_pred, 1)).astype( + "int64" + ) + predicted_positives = 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_predicted_positives = ivy.multiply(predicted_positives, sample_weight) + weighted_actual_positives = ivy.multiply(actual_positives, sample_weight) + + # Compute precision and recall with checks for division by zero + precision = 0.0 + recall = 0.0 + if ivy.sum(weighted_predicted_positives) > 0: + precision = ivy.sum(weighted_true_positives) / ivy.sum( + weighted_predicted_positives + ) + if ivy.sum(weighted_actual_positives) > 0: + recall = ivy.sum(weighted_true_positives) / ivy.sum(weighted_actual_positives) + + # Compute F1 score with a check to avoid division by zero + if precision + recall > 0: + ret = 2 * (precision * recall) / (precision + recall) + else: + ret = ivy.array(0.0) # If both precision and recall are zero, F1 score is zero + + ret = ret.astype("float64") + return ret + + +@to_ivy_arrays_and_back +def hamming_loss(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 the Hamming loss + incorrect_predictions = ivy.not_equal(y_true, y_pred).astype("int64") + # Apply sample weights + weighted_incorrect_predictions = ivy.multiply(incorrect_predictions, sample_weight) + + # Compute hamming loss + loss = ivy.sum(weighted_incorrect_predictions) / y_true.shape[0] + + loss = loss.astype("float64") + return loss + + +@to_ivy_arrays_and_back +def precision_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 predicted positives + true_positives = ivy.logical_and(ivy.equal(y_true, 1), ivy.equal(y_pred, 1)).astype( + "int64" + ) + predicted_positives = ivy.equal(y_pred, 1).astype("int64") + + # Apply sample weights + weighted_true_positives = ivy.multiply(true_positives, sample_weight) + weighted_predicted_positives = ivy.multiply(predicted_positives, sample_weight) + + # Compute precision + ret = ivy.sum(weighted_true_positives) / ivy.sum(weighted_predicted_positives) + + 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 406ae7c7d22a2..1f14400186012 100644 --- a/ivy/functional/frontends/sklearn/model_selection/_split.py +++ b/ivy/functional/frontends/sklearn/model_selection/_split.py @@ -77,16 +77,18 @@ def _iter_test_indices(self, X=None, y=None, groups=None): 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] n_classes = len(y_idx) y_order = ivy.sort(y_encoded) - allocation = ivy.asarray([ - ivy.bincount(y_order[i :: self.n_splits], minlength=n_classes) - for i in range(self.n_splits) - ]) + allocation = ivy.asarray( + [ + ivy.bincount(y_order[i :: self.n_splits], minlength=n_classes) + for i in range(self.n_splits) + ] + ) test_folds = ivy.empty(len(y), dtype="int64") for k in range(n_classes): folds_for_class = ivy.arange(self.n_splits).repeat(allocation[:, k]) @@ -121,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 diff --git a/ivy/functional/frontends/sklearn/tree/__init__.py b/ivy/functional/frontends/sklearn/tree/__init__.py index d17f1a0841699..b726da4f4a4c2 100644 --- a/ivy/functional/frontends/sklearn/tree/__init__.py +++ b/ivy/functional/frontends/sklearn/tree/__init__.py @@ -1,2 +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 d7772084b4d60..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): @@ -51,10 +57,114 @@ 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 + ) + + 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] + + # Classification + + if self.n_outputs_ == 1: + return ivy.gather(self.classes_, ivy.argmax(proba, axis=1), axis=0) + + 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 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 8f41d31818161..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"): @@ -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/func_wrapper.py b/ivy/functional/frontends/tensorflow/func_wrapper.py index c72ff5565a19d..a25c8418885e2 100644 --- a/ivy/functional/frontends/tensorflow/func_wrapper.py +++ b/ivy/functional/frontends/tensorflow/func_wrapper.py @@ -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 ---------- @@ -142,10 +140,10 @@ def _inputs_to_ivy_arrays_tf(*args, **kwargs): 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. + """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 ---------- @@ -199,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 065a69852ed83..d5c8e03b63106 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 --- # @@ -86,16 +86,17 @@ 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.15.0 and below": ("float16",)}, "tensorflow") +@with_unsupported_dtypes( + {"2.15.0 and below": ("complex64", "complex128")}, "tensorflow" +) def clip_by_value(t, clip_value_min, clip_value_max): ivy.utils.assertions.check_all_or_any_fn( clip_value_min, @@ -213,7 +214,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, @@ -307,6 +308,9 @@ def norm(tensor, ord="euclidean", axis=None, keepdims=None, name=None): ) +@with_supported_dtypes( + {"2.15.0 and below": ("uint8", "int8", "int32", "int64")}, "tensorflow" +) @to_ivy_arrays_and_back def one_hot( indices: ivy.Array, @@ -401,6 +405,12 @@ def scan( return ivy.associative_scan(elems, fn, reverse=reverse) +@with_supported_dtypes({"2.17.0 and below": ("int32", "int64")}, "tensorflow") +@to_ivy_arrays_and_back +def scatter_nd(indices, updates, shape, name=None): + return ivy.astype(ivy.scatter_nd(indices, updates, shape=shape), updates.dtype) + + @to_ivy_arrays_and_back def searchsorted(sorted_sequence, values, side="left", out_type="int32"): out_type = to_ivy_dtype(out_type) 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 9abc0a84825ad..22da3aded0b23 100644 --- a/ivy/functional/frontends/tensorflow/keras/activations.py +++ b/ivy/functional/frontends/tensorflow/keras/activations.py @@ -1,7 +1,7 @@ import ivy import ivy.functional.frontends.tensorflow as tf_frontend from ivy.functional.frontends.tensorflow.func_wrapper import to_ivy_arrays_and_back -from ivy import with_supported_dtypes +from ivy import with_supported_dtypes, with_unsupported_dtypes ACTIVATION_FUNCTIONS = [ @@ -16,6 +16,21 @@ ] +# --- 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.15.0 and below": ("float16", "float32", "float64")}, "tensorflow", @@ -97,6 +112,10 @@ def linear(x): return ivy.array(x) +@with_unsupported_dtypes( + {"2.15.0 and below": ("complex",)}, + "tensorflow", +) @to_ivy_arrays_and_back def relu(x, alpha=0.0, max_value=None, threshold=0.0): return ivy.relu(x) @@ -132,13 +151,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..2d3159881ba83 --- /dev/null +++ b/ivy/functional/frontends/tensorflow/keras/backend.py @@ -0,0 +1,122 @@ +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, + ) + + +def sum(x, axis=None, keepdims=False): + return tf_frontend.reduce_sum(x, axis, keepdims) diff --git a/ivy/functional/frontends/tensorflow/keras/metrics.py b/ivy/functional/frontends/tensorflow/keras/metrics.py index 2c8402c8b8067..d32ef36cf1ebc 100644 --- a/ivy/functional/frontends/tensorflow/keras/metrics.py +++ b/ivy/functional/frontends/tensorflow/keras/metrics.py @@ -96,10 +96,15 @@ def _top_k(input, topk): labels = ivy.shape(predictions)[1] # float comparison? - return ivy.array([ - (0 <= res < labels and ivy.min(top_k[ind] - predictions[ind, res]) <= 1e-9) - for ind, res in enumerate(targets) - ]) + return ivy.array( + [ + ( + 0 <= res < labels + and ivy.min(top_k[ind] - predictions[ind, res]) <= 1e-9 + ) + for ind, res in enumerate(targets) + ] + ) reshape = False y_true = ivy.array(y_true) diff --git a/ivy/functional/frontends/tensorflow/linalg.py b/ivy/functional/frontends/tensorflow/linalg.py index b0e8bdfdc7c5f..01a8f293f4497 100644 --- a/ivy/functional/frontends/tensorflow/linalg.py +++ b/ivy/functional/frontends/tensorflow/linalg.py @@ -458,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 c3a56fa3ec55f..e429b1a31fe02 100644 --- a/ivy/functional/frontends/tensorflow/math.py +++ b/ivy/functional/frontends/tensorflow/math.py @@ -13,6 +13,138 @@ ) +# --- 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"), @@ -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) @@ -104,6 +244,41 @@ def atanh(x, name="atanh"): return ivy.atanh(x) +@with_supported_dtypes( + {"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", @@ -289,6 +464,9 @@ def greater(x, y, name=None): return ivy.greater(x, y) +@with_unsupported_dtypes( + {"2.15.0 and below": ("complex64", "complex128")}, "tensorflow" +) @to_ivy_arrays_and_back def greater_equal(x, y, name=None): x, y = check_tensorflow_casting(x, y) @@ -369,9 +547,11 @@ 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 @@ -383,6 +563,9 @@ def l2_normalize(x, axis=None, epsilon=1e-12, name=None): @to_ivy_arrays_and_back +@with_unsupported_dtypes( + {"2.15.0 and below": ("complex64", "complex128")}, "tensorflow" +) def less(x, y, name="None"): x, y = check_tensorflow_casting(x, y) return ivy.less(x, y) @@ -444,17 +627,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.2 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) @@ -571,10 +756,12 @@ def reduce_max(input_tensor, axis=None, keepdims=False, name="reduce_max"): @to_ivy_arrays_and_back -def reduce_mean(input_tensor, axis=None, keepdims=False, name="reduce_mean"): +def reduce_mean( + input_tensor, axis=None, keepdims=False, dtype=None, name="reduce_mean" +): if ivy.exists(axis): axis = ivy.to_list(axis) - return ivy.mean(input_tensor, axis=axis, keepdims=keepdims) + return ivy.mean(input_tensor, axis=axis, keepdims=keepdims, dtype=dtype) @to_ivy_arrays_and_back @@ -637,6 +824,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) @@ -847,8 +1053,8 @@ def xlogy(x, y, name=None): def zero_fraction(value, name="zero_fraction"): 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)) diff --git a/ivy/functional/frontends/tensorflow/nn.py b/ivy/functional/frontends/tensorflow/nn.py index bf143ebe8aca5..ca340335899a3 100644 --- a/ivy/functional/frontends/tensorflow/nn.py +++ b/ivy/functional/frontends/tensorflow/nn.py @@ -100,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 @@ -127,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) @@ -160,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, @@ -198,7 +199,6 @@ def conv2d_transpose( dilations = 1 if dilations is None else dilations strides, dilations = _reduce_strides_dilations(2, strides, dilations) padding = _reduce_padding(padding, data_format) - filters = filters.swapaxes(-2, -1) return ivy.conv2d_transpose( input, filters, @@ -235,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, @@ -317,9 +316,9 @@ def depthwise_conv2d( dilations = 1 if dilations is None else dilations strides, dilations = _reduce_strides_dilations(2, strides, dilations) fc = filter.shape[-2] - filter = filter.reshape([ - *filter.shape[0:2], 1, filter.shape[-2] * filter.shape[-1] - ]) + filter = filter.reshape( + [*filter.shape[0:2], 1, filter.shape[-2] * filter.shape[-1]] + ) return ivy.conv_general_dilated( input, filter, @@ -636,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/raw_ops.py b/ivy/functional/frontends/tensorflow/raw_ops.py index 030e2be87b6fc..61c87dcb5c76b 100644 --- a/ivy/functional/frontends/tensorflow/raw_ops.py +++ b/ivy/functional/frontends/tensorflow/raw_ops.py @@ -14,6 +14,7 @@ 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( @@ -248,6 +249,7 @@ ) 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( { @@ -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)) @@ -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) @@ -850,6 +862,39 @@ 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(): @@ -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/tensor.py b/ivy/functional/frontends/tensorflow/tensor.py index e70c78c13e1a5..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 ( @@ -244,9 +242,9 @@ def __str__(self): if self.rank is None: return "" elif self.rank == 1: - return "(%s,)" % self._dims[0] + return f"({self._dims[0]},)" else: - return "(%s)" % ", ".join(str(d) for d in self._dims) + return f'({", ".join(str(d) for d in self._dims)})' # Properties # # ---------- # @@ -334,7 +332,7 @@ def unknown_shape(rank=None, **kwargs): if rank is None and "ndims" in kwargs: rank = kwargs.pop("ndims") if kwargs: - raise TypeError("Unknown argument: %s" % kwargs) + raise TypeError(f"Unknown argument: {kwargs}") if rank is None: return TensorShape(None) else: 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 963e9894d24af..c1fd0d888f667 100644 --- a/ivy/functional/frontends/torch/__init__.py +++ b/ivy/functional/frontends/torch/__init__.py @@ -185,14 +185,19 @@ } +@handle_exceptions +def device(dev): + return ivy.default_device(dev) + + @handle_exceptions def promote_types_torch( type1: Union[ivy.Dtype, ivy.NativeDtype], 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 +215,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 +228,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 @@ -258,9 +264,9 @@ def promote_types_of_torch_inputs( return x1, x2 -from . import utils from . import nn from .nn.functional import softmax, relu, lstm +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 9cc767415b192..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.1 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 80d55d6957f39..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,14 +99,14 @@ def fmin(input, other, *, out=None): ) -@with_unsupported_dtypes({"2.1.1 and below": ("complex64", "complex128")}, "torch") +@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.1.1 and below": ("complex64", "complex128")}, "torch") +@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) @@ -142,7 +143,9 @@ def isfinite(input): return ivy.isfinite(input) -@with_unsupported_dtypes({"2.1.1 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,)) @@ -196,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) @@ -203,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) @@ -210,14 +215,14 @@ def isposinf(input, *, out=None): return ivy.logical_and(is_inf, pos_sign_bit, out=out) -@with_unsupported_dtypes({"2.1.1 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.1 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): @@ -241,44 +246,48 @@ def kthvalue(input, k, dim=-1, keepdim=False, *, out=None): return ret -@with_unsupported_dtypes({"2.1.1 and below": ("complex64", "complex128")}, "torch") +@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.1.1 and below": ("complex64", "complex128")}, "torch") +@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.1 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): @@ -287,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.1 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: @@ -295,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 866d4a9cb0459..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.1 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.1 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.1 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.1 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.1 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.1 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 c79cdd9782ceb..c7df1998d4faa 100644 --- a/ivy/functional/frontends/torch/func_wrapper.py +++ b/ivy/functional/frontends/torch/func_wrapper.py @@ -131,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 @@ -169,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. @@ -267,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. @@ -277,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 e904fda02498b..5e46854039dcf 100644 --- a/ivy/functional/frontends/torch/indexing_slicing_joining_mutating_ops.py +++ b/ivy/functional/frontends/torch/indexing_slicing_joining_mutating_ops.py @@ -74,7 +74,7 @@ def conj(input): # diagonal_scatter @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -89,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}" @@ -215,7 +215,7 @@ def index_copy(input, dim, index, source, *, out=None): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "uint16", "uint32", "uint64", @@ -342,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 @@ -401,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) @@ -420,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) diff --git a/ivy/functional/frontends/torch/linalg.py b/ivy/functional/frontends/torch/linalg.py index 7f5e9d87b4de6..84eee15d96966 100644 --- a/ivy/functional/frontends/torch/linalg.py +++ b/ivy/functional/frontends/torch/linalg.py @@ -9,36 +9,42 @@ @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 and below": ("float32", "float64", "complex32", "complex64")}, "torch" + {"2.2 and below": ("float32", "float64", "complex32", "complex64", "complex128")}, + "torch", ) def cholesky(input, *, upper=False, out=None): return ivy.cholesky(input, upper=upper, out=out) @to_ivy_arrays_and_back +@with_supported_dtypes( + {"2.2 and below": ("float32", "float64", "complex32", "complex64")}, "torch" +) def cholesky_ex(input, *, upper=False, check_errors=False, out=None): try: + results = namedtuple("cholesky_ex", ["L", "info"]) matrix = ivy.cholesky(input, upper=upper, out=out) info = ivy.zeros(input.shape[:-2], dtype=ivy.int32) - return matrix, info + return results(matrix, info) except RuntimeError as e: if check_errors: - raise RuntimeError(e) + raise RuntimeError(e) from e else: + results = namedtuple("cholesky_ex", ["L", "info"]) matrix = input * math.nan info = ivy.ones(input.shape[:-2], dtype=ivy.int32) - return matrix, info + return results(matrix, info) @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.1 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.1 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 +52,7 @@ def cross(input, other, *, dim=None, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +69,13 @@ def divide(input, other, *, rounding_mode=None, out=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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.1 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 +84,7 @@ def eigh(A, UPLO="L", *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +95,7 @@ def eigvals(input, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +108,7 @@ def eigvalsh(input, UPLO="L", *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +116,7 @@ def inv(A, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +135,58 @@ def inv_ex(A, *, check_errors=False, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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.1 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.1 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.1 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)) - return ivy.matrix_norm(input, ord=ord, axis=dim, keepdims=keepdim, out=out) + return ivy.matrix_norm( + input, ord=ord, axis=dim, keepdims=keepdim, dtype=dtype, out=out + ) @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +194,15 @@ def matrix_power(A, n, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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.1 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 +210,7 @@ def multi_dot(tensors, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +221,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.1 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 +253,7 @@ def pinv(input, *, atol=None, rtol=None, hermitian=False, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +271,7 @@ def qr(A, mode="reduced", *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +287,7 @@ def slogdet(A, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +301,7 @@ def solve(A, B, *, left=True, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +319,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 +329,7 @@ def solve_ex(A, B, *, left=True, check_errors=False, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +338,7 @@ def svd(A, /, *, full_matrices=True, driver=None, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +349,7 @@ def svdvals(A, *, driver=None, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +368,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 +376,14 @@ def tensorinv(input, ind=2, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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.1 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 +416,7 @@ def vander(x, N=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 +426,7 @@ def vecdot(x, y, *, dim=-1, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 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 23eeef185e73e..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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 and below": ("complex64", "complex128")}, + {"2.2 and below": ("complex64", "complex128")}, "torch", ) @to_ivy_arrays_and_back diff --git a/ivy/functional/frontends/torch/nn/functional/convolution_functions.py b/ivy/functional/frontends/torch/nn/functional/convolution_functions.py index 782efc8e75f9b..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() @@ -38,8 +37,6 @@ def _conv(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): return ret -# ToDo: add support for dilation > 1 -# ToDo: add support for output_padding > padding def _conv_transpose( input, weight, @@ -54,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, @@ -67,12 +74,17 @@ 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 @@ -91,70 +103,11 @@ def _get_transpose_pad(padding, output_padding, dims): return asymmetric_padding -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, - ) - - 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, - ) - - # --- Main --- # # ------------ # -@with_unsupported_dtypes({"2.1.1 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( @@ -168,7 +121,7 @@ def conv1d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): ) -@with_unsupported_dtypes({"2.1.1 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( @@ -182,7 +135,7 @@ def conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): ) -@with_unsupported_dtypes({"2.1.1 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( @@ -196,7 +149,7 @@ def conv3d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1): ) -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv_transpose1d( input, @@ -208,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.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv_transpose2d( input, @@ -234,20 +202,20 @@ def conv_transpose2d( ): if ivy.current_backend_str() in ["torch", "tensorflow"]: # these two backends support explicit padding, no need for conv_general_dilated - weight = ivy.permute_dims(weight, axes=(2, 3, 0, 1)) 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: - _conv_transpose( + return _conv_transpose( input, weight, bias=bias, @@ -259,7 +227,7 @@ def conv_transpose2d( ) -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def conv_transpose3d( input, @@ -271,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 ba8b6f0930cc1..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.1 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.1 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,12 +42,14 @@ 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.1 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([ - abs(input[i] - input[j]) - for i in range(len(input) - 1) - for j in range(i + 1, len(input)) - ]) + x = ivy.array( + [ + abs(input[i] - input[j]) + for i in range(len(input) - 1) + for j in range(i + 1, len(input)) + ] + ) return ivy.vector_norm(x, ord=p, axis=1) diff --git a/ivy/functional/frontends/torch/nn/functional/dropout_functions.py b/ivy/functional/frontends/torch/nn/functional/dropout_functions.py index 3247afeb2cd66..a4d2b296661ad 100644 --- a/ivy/functional/frontends/torch/nn/functional/dropout_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/dropout_functions.py @@ -7,8 +7,8 @@ # ToDo: this function will be simplified once ivy.alpha_dropout is implemented @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 and below": ("float16",)}, "torch") -@with_unsupported_dtypes({"2.5.2 and below": ("float16", "bfloat16")}, "paddle") +@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 @@ -28,13 +28,13 @@ def alpha_dropout(input, p=0.5, training=False, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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, scale=True, training=training) @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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) @@ -42,7 +42,7 @@ def dropout1d(input, p=0.5, training=True, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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") @@ -55,7 +55,7 @@ def dropout2d(input, p=0.5, training=True, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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 0f3b1cf74a82b..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.1 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.1 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 e4bafdaed2e47..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.1 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 2ba4f45d333fa..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.1 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.1 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" ): @@ -166,10 +166,12 @@ def calculate_loss(x1, x2, target): if target.ndim == 0: loss = calculate_loss(input1, input2, target) else: - loss = ivy.array([ - calculate_loss(input1[i], input2[i], target[i]) - for i in range(input1.shape[0]) - ]) + loss = ivy.array( + [ + calculate_loss(input1[i], input2[i], target[i]) + for i in range(input1.shape[0]) + ] + ) reduction = _get_reduction(reduction, size_average, reduce) loss = reduction(loss) @@ -212,7 +214,7 @@ def cross_entropy( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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) @@ -244,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.1 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, @@ -279,7 +281,7 @@ def huber_loss( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.1 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 ): @@ -295,7 +297,7 @@ def kl_div( @to_ivy_arrays_and_back -@with_supported_dtypes({"2.1.1 and below": ("float", "complex")}, "torch") +@with_supported_dtypes({"2.2 and below": ("float", "complex")}, "torch") def l1_loss( input, target, @@ -310,7 +312,7 @@ def l1_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def margin_ranking_loss( input1, input2, @@ -329,7 +331,7 @@ def margin_ranking_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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) @@ -338,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.1 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" ): @@ -358,7 +360,7 @@ def multilabel_margin_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def multilabel_soft_margin_loss( input, target, @@ -388,7 +390,7 @@ def multilabel_soft_margin_loss( @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "int8", "int16", "int32")}, "torch" + {"2.2 and below": ("float16", "int8", "int16", "int32")}, "torch" ) def nll_loss( input, @@ -434,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.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def poisson_nll_loss( input, target, @@ -461,7 +463,7 @@ def poisson_nll_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def smooth_l1_loss( input, target, @@ -474,7 +476,7 @@ def smooth_l1_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def soft_margin_loss( input, target, @@ -486,7 +488,7 @@ def soft_margin_loss( @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def triplet_margin_loss( anchor, positive, @@ -541,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.1 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 2c606b3eeee7f..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.1 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.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -63,7 +63,7 @@ def glu(input, dim=-1): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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 @@ -100,30 +100,30 @@ def hardswish(input, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1.1 and below": ("float",)}, "torch") +@with_supported_dtypes({"2.2 and below": ("float",)}, "torch") def local_response_norm(input, size, alpha=0.0001, beta=0.75, k=1.0): non_batched = input.ndim == 3 if non_batched: @@ -137,7 +137,7 @@ def local_response_norm(input, size, alpha=0.0001, beta=0.75, k=1.0): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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)) @@ -149,7 +149,7 @@ def log_softmax(input, dim=None, _stacklevel=3, dtype=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -188,7 +188,7 @@ def relu(input, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 and below": ("complex",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("complex",)}, "torch") def relu6(input, inplace=False): return ivy.relu6(input) @@ -199,7 +199,7 @@ def relu_(input): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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) @@ -212,13 +212,13 @@ def rrelu(input, lower=1.0 / 8, upper=1.0 / 3, training=False, inplace=False): ) -@with_unsupported_dtypes({"2.1.1 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.1 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 ): @@ -239,19 +239,19 @@ def selu(input, inplace=False): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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.1 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.1 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)) @@ -259,7 +259,7 @@ def softmax(input, dim=None, _stacklevel=3, dtype=None): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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)) @@ -269,7 +269,7 @@ def softmin(input, dim=None, dtype=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -293,23 +293,23 @@ def softsign(input): @to_ivy_arrays_and_back -@with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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 bc4bbfabf1083..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.1 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.1 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.1 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.1 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 5b5becf55fd29..c442c55afc917 100644 --- a/ivy/functional/frontends/torch/nn/functional/pooling_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/pooling_functions.py @@ -3,6 +3,7 @@ # local import ivy +import ivy.functional.frontends.torch as torch_frontend from ivy import with_unsupported_dtypes from ivy.functional.frontends.torch.func_wrapper import ( to_ivy_arrays_and_back, @@ -11,7 +12,7 @@ @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -25,7 +26,7 @@ def adaptive_avg_pool1d(input, output_size): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -34,12 +35,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.1 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -57,7 +58,28 @@ def adaptive_max_pool2d( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16",)}, + { + "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 @@ -83,7 +105,7 @@ def avg_pool1d( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16",)}, + {"2.2 and below": ("float16",)}, "torch", ) @to_ivy_arrays_and_back @@ -111,7 +133,7 @@ def avg_pool2d( @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16")}, + {"2.2 and below": ("float16", "bfloat16")}, "torch", ) @to_ivy_arrays_and_back @@ -140,7 +162,7 @@ def avg_pool3d( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -172,7 +194,7 @@ def lp_pool1d(input, norm_type, kernel_size, stride=None, ceil_mode=False): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -201,7 +223,7 @@ 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.1.1 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def max_pool1d( input, @@ -216,7 +238,13 @@ def max_pool1d( stride = kernel_size if not isinstance(padding, int): padding = [(pad, pad) for pad in padding] - return ivy.max_pool1d( + if input.ndim == 2: + without_batch_dim = True + input = ivy.expand_dims(input, axis=0) + else: + without_batch_dim = False + + ret = ivy.max_pool1d( input, kernel_size, stride, @@ -225,9 +253,12 @@ def max_pool1d( dilation=dilation, ceil_mode=ceil_mode, ) + if without_batch_dim: + ret = ret[0] + return ret -@with_unsupported_dtypes({"2.1.1 and below": ("float16",)}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def max_pool2d( input, @@ -238,22 +269,83 @@ 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( + if input.ndim == 3: + without_batch_dim = True + input = ivy.expand_dims(input, axis=0) + else: + without_batch_dim = False + + output = ivy.max_pool2d( input, kernel_size, stride, - padding, + ([(pad, pad) for pad in padding] if not isinstance(padding, int) else padding), data_format="NCHW", dilation=dilation, ceil_mode=ceil_mode, ) + if return_indices: + if isinstance(stride, (list, tuple)) and len(stride) == 1: + stride = stride[0] + + in_shape = input.shape + H = in_shape[-2] + W = in_shape[-1] + n_indices = H * W + + # calculate the indices within the input tensor + # for each position in the sliding window + input_indices = torch_frontend.arange(0, n_indices, dtype=torch_frontend.int64) + input_indices = input_indices.reshape((1, 1, H, W)) + unfolded_indices = torch_frontend.nn.functional.unfold( + input_indices, + kernel_size=kernel_size, + padding=padding, + dilation=dilation, + stride=stride, + ).permute((0, 2, 1))[0] + + # find the indices of the max value for each position of the sliding window + input = torch_frontend.nn.functional.pad( + input, + [padding] * 4 if isinstance(padding, int) else padding * 2, + value=float("-inf"), + ) + unfolded_values = torch_frontend.nn.functional.unfold( + input, kernel_size=kernel_size, padding=0, dilation=dilation, stride=stride + ) + unfolded_values_shape = unfolded_values.shape + unfolded_indices = unfolded_indices.repeat( + unfolded_values_shape[0], unfolded_values_shape[1], 1, 1 + ) + unfolded_values = unfolded_values.reshape( + input.shape[0], + input.shape[1], + unfolded_values.shape[1] // input.shape[1], + unfolded_values.shape[2], + ) + indices = torch_frontend.argmax(unfolded_values, dim=2) + + # gather the indices within the input tensor of the max values + indices = torch_frontend.gather( + unfolded_indices, -1, torch_frontend.unsqueeze(indices, -1) + ) + indices = indices.reshape(output.shape) + + if without_batch_dim: + output = output[0] + if return_indices: + indices = indices[0] -@with_unsupported_dtypes({"2.1.1 and below": ("float16",)}, "torch") + if return_indices: + return output, indices + return output + + +@with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") @to_ivy_arrays_and_back def max_pool3d( input, @@ -268,7 +360,13 @@ def max_pool3d( stride = kernel_size if not isinstance(padding, int): padding = [(pad, pad) for pad in padding] - return ivy.max_pool3d( + if input.ndim == 4: + without_batch_dim = True + input = ivy.expand_dims(input, axis=0) + else: + without_batch_dim = False + + ret = ivy.max_pool3d( input, kernel_size, stride, @@ -277,3 +375,6 @@ 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 1be9407cd50f9..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.1 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 8b661a78b3fbc..830b366469143 100644 --- a/ivy/functional/frontends/torch/nn/functional/vision_functions.py +++ b/ivy/functional/frontends/torch/nn/functional/vision_functions.py @@ -11,10 +11,12 @@ def _handle_padding_shape(padding, n, mode): - padding = tuple([ - (padding[i * 2], padding[i * 2 + 1]) - for i in range(int(len(padding) / 2) - 1, -1, -1) - ]) + padding = tuple( + [ + (padding[i * 2], padding[i * 2 + 1]) + for i in range(int(len(padding) / 2) - 1, -1, -1) + ] + ) if mode == "circular": padding = padding + ((0, 0),) * (n - len(padding)) else: @@ -28,7 +30,7 @@ def _handle_padding_shape(padding, n, mode): # ------------ # -@with_unsupported_dtypes({"2.1.1 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: @@ -91,7 +93,7 @@ def cubic_conv2(A, x): return ((A * x - 5 * A) * x + 8 * A) * x - 4 * A -@with_supported_dtypes({"2.1.1 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 @@ -346,7 +348,7 @@ def grid_sample_padding(grid, padding_mode, align_corners, borders=None): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "float16", ) @@ -386,13 +388,35 @@ def interpolate( mode=mode, scale_factor=scale_factor, recompute_scale_factor=recompute_scale_factor, - align_corners=True if align_corners else False, + align_corners=bool(align_corners), antialias=antialias, ) @to_ivy_arrays_and_back def pad(input, pad, mode="constant", value=0): + # deal with any negative pad values + if any([pad_value < 0 for pad_value in pad]): + pad = list(pad) + slices = [] + for n in reversed(range(len(pad) // 2)): + i = n * 2 + j = i + 1 + start = None + stop = None + if pad[i] < 0: + start = -pad[i] + pad[i] = 0 + if pad[j] < 0: + stop = pad[j] + pad[j] = 0 + slices.append(slice(start, stop)) + ndim = len(input.shape) + while len(slices) < ndim: + slices.insert(0, slice(None)) + input = input[tuple(slices)] + + value = 0 if value is None else value mode_dict = { "constant": "constant", "reflect": "reflect", @@ -503,7 +527,7 @@ def reflect(x, low2, high2): return x -@with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") +@with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") @to_ivy_arrays_and_back def upsample( input, @@ -521,7 +545,7 @@ def upsample( ) -@with_unsupported_dtypes({"2.1.1 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( @@ -529,7 +553,7 @@ def upsample_bilinear(input, size=None, scale_factor=None): ) -@with_unsupported_dtypes({"2.1.1 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/module.py b/ivy/functional/frontends/torch/nn/modules/module.py index 5458f50af041a..1cc8e668db55f 100644 --- a/ivy/functional/frontends/torch/nn/modules/module.py +++ b/ivy/functional/frontends/torch/nn/modules/module.py @@ -1,131 +1,82 @@ -from collections import OrderedDict -import functools -from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple, Union -import warnings -import weakref +# global import ivy -from ivy.functional.frontends.torch.nn.parameter import Parameter +from collections import OrderedDict +from typing import Any, Dict, Iterator, List, Optional, Set, Tuple, Callable +import threading +# local +from ivy.functional.frontends.torch.nn.parameter import Parameter from ivy.functional.frontends.torch.tensor import Tensor -from ivy.functional.frontends.torch.utils import hooks - -_grad_t = Union[Tuple[Tensor, ...], Tensor] - - -class _WrappedHook: - def __init__(self, hook: Callable, module: Optional["Module"] = None): - self.hook: Callable = hook - functools.update_wrapper(self, hook) - - self.with_module: bool = False - - if module is not None: - self.module: weakref.ReferenceType[Module] = weakref.ref(module) - self.with_module = True - - def __call__(self, *args: Any, **kwargs: Any) -> Any: - if self.with_module: - module = self.module() - if module is None: - raise RuntimeError("You are trying to call the hook of a dead Module!") - return self.hook(module, *args, **kwargs) - return self.hook(*args, **kwargs) - - def __getstate__(self) -> Dict: - result = {"hook": self.hook, "with_module": self.with_module} - if self.with_module: - result["module"] = self.module() - - return result - - def __setstate__(self, state: Dict): - self.hook = state["hook"] - self.with_module = state["with_module"] - - if self.with_module: - if state["module"] is None: - raise RuntimeError( - "You are trying to revive the hook of a dead Module!" - ) - self.module = weakref.ref(state["module"]) class Module(ivy.Module): - dump_patches: bool = False _version: int = 1 training: bool _parameters: Dict[str, Optional[Parameter]] - _buffers: Dict[str, Optional[Tensor]] - _non_persistent_buffers_set: Set[str] - _backward_pre_hooks: Dict[int, Callable] - _backward_hooks: Dict[int, Callable] - _is_full_backward_hook: Optional[bool] - _forward_hooks: Dict[int, Callable] - _forward_hooks_with_kwargs: Dict[int, bool] - _forward_hooks_always_called: Dict[int, bool] - _forward_pre_hooks: Dict[int, Callable] - _forward_pre_hooks_with_kwargs: Dict[int, bool] - _state_dict_hooks: Dict[int, Callable] - _load_state_dict_pre_hooks: Dict[int, Callable] - _state_dict_pre_hooks: Dict[int, Callable] - _load_state_dict_post_hooks: Dict[int, Callable] _modules: Dict[str, Optional["Module"]] - call_super_init: bool = False - _compiled_call_impl: Optional[Callable] = None - def __init__( - self, *args, device=None, devices=None, inplace_update=False, **kwargs - ) -> None: - self.__setattr__("_args", args) - self.__setattr__("_kwargs", kwargs) - self.__setattr__( - "_update_v", - self._inplace_update_v if inplace_update else self._replace_update_v, + 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, ) - self.__setattr__("training", True) - self.__setattr__("_parameters", OrderedDict()) - self.__setattr__("_buffers", OrderedDict()) - self.__setattr__("_non_persistent_buffers_set", set()) - self.__setattr__("_backward_pre_hooks", OrderedDict()) - self.__setattr__("_backward_hooks", OrderedDict()) - self.__setattr__("_is_full_backward_hook", None) - self.__setattr__("_forward_hooks", OrderedDict()) - self.__setattr__("_forward_hooks_with_kwargs", OrderedDict()) - self.__setattr__("_forward_hooks_always_called", OrderedDict()) - self.__setattr__("_forward_pre_hooks", OrderedDict()) - self.__setattr__("_forward_pre_hooks_with_kwargs", OrderedDict()) - self.__setattr__("_state_dict_hooks", OrderedDict()) - self.__setattr__("_state_dict_pre_hooks", OrderedDict()) - self.__setattr__("_load_state_dict_pre_hooks", OrderedDict()) - self.__setattr__("_load_state_dict_post_hooks", OrderedDict()) - self.__setattr__("_modules", OrderedDict()) - ivy.Module.__init__( - self, *args, device=device, devices=devices, build_mode="explicit", **kwargs + super().__setattr__("_frontend_module", True) + super().__setattr__( + "_attr_mapping", {"_parameters": "v", "_modules": "module_dict"} ) def _create_variables(self, device=None, dtype=None): - return self._native_params - - def _build(self, *args, **kwargs): - self._native_params = ivy.Container( + # 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 dict(self.named_parameters()).items() - ]) - ), - dynamic_backend=False, + for k, v in self.__dict__.items() + if isinstance(v, Parameter) + and not k.startswith( + ("_"), + ) + ] + ) ) - - @staticmethod - def _inplace_update(p, v): - p.data = v.data - - def _inplace_update_v(self, new_v): - ivy.Container.cont_multi_map( - lambda xs, kc: self._inplace_update(xs[0], xs[1]), - [self._native_params, new_v], + # 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 @@ -134,7 +85,7 @@ def _replace_update_v(self, new_v, native=None): for k, v in new_v.items(): if isinstance(v, ivy.Container): # noinspection PyProtectedMember - native._modules[k] = self._replace_update_v(v, native._modules[k]) + native.module_dict[k] = self._replace_update_v(v, native.module_dict[k]) elif isinstance(v, Parameter): # noinspection PyProtectedMember native.__setattr__(k, v) @@ -150,78 +101,17 @@ def _replace_update_v(self, new_v, native=None): ) 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 _forward(self, *a, **kw): - ret = self._wrapped_call_impl(*a, **kw) + ret = self._call_impl(*a, **kw) return ret - def register_buffer( - self, name: str, tensor: Optional[Tensor], persistent: bool = True - ) -> None: - if "_buffers" not in self.__dict__: - raise AttributeError("cannot assign buffer before Module.__init__() call") - elif not isinstance(name, str): - raise TypeError(f"buffer name should be a string. Got {type(name)}") - elif "." in name: - raise KeyError('buffer name can\'t contain "."') - elif name == "": - raise KeyError('buffer name can\'t be empty string ""') - elif hasattr(self, name) and name not in self._buffers: - raise KeyError(f"attribute '{name}' already exists") - elif tensor is not None and not isinstance(tensor, Tensor): - raise TypeError( - f"cannot assign '{type(tensor)}' object to buffer '{name}' " - "(torch Tensor or None required)" - ) - else: - for hook in _global_buffer_registration_hooks.values(): - output = hook(self, name, tensor) - if output is not None: - tensor = output - self._buffers[name] = tensor - if persistent: - self._non_persistent_buffers_set.discard(name) - else: - self._non_persistent_buffers_set.add(name) - - def register_parameter(self, name: str, param: Optional[Parameter]) -> None: - if "_parameters" not in self.__dict__: - raise AttributeError( - "cannot assign parameter before Module.__init__() call" - ) - - elif not isinstance(name, str): - raise TypeError(f"parameter name should be a string. Got {type(name)}") - elif "." in name: - raise KeyError('parameter name can\'t contain "."') - elif name == "": - raise KeyError('parameter name can\'t be empty string ""') - - if param is None: - self._parameters[name] = None - elif not isinstance(param, Parameter): - raise TypeError( - f"cannot assign '{type(param)}' object to parameter '{name}' " - "(torch.nn.Parameter or None required)" - ) - elif param.grad_fn: - raise ValueError( - f"Cannot assign non-leaf Tensor to parameter '{name}'. Model " - f"parameters must be created explicitly. To express '{name}' " - "as a function of another Tensor, compute the value in " - "the forward() method." - ) - else: - for hook in _global_parameter_registration_hooks.values(): - output = hook(self, name, param) - if output is not None: - param = output - self._parameters[name] = param - 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") @@ -233,12 +123,28 @@ def add_module(self, name: str, module: Optional["Module"]) -> None: raise KeyError(f'module name can\'t contain ".", got: {name}') elif name == "": raise KeyError('module name can\'t be empty string ""') - for hook in _global_module_registration_hooks.values(): - output = hook(self, name, module) - if output is not None: - module = output + self._modules[name] = module + super().__setattr__(name, module) + + def apply(self, fn: Callable[["Module"], None]): + for module in self.children(): + if hasattr(module, "apply"): + module.apply(fn) + else: + fn(module) + fn(self) + return self + + def register_buffer( + self, name: str, value: Optional["Tensor"], persistent: bool = False + ) -> 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) @@ -251,7 +157,6 @@ def get_submodule(self, target: str) -> "Module": mod: Module = self for item in atoms: - if not hasattr(mod, item): raise AttributeError( mod._get_name() + " has no attribute `" + item + "`" @@ -260,43 +165,13 @@ def get_submodule(self, target: str) -> "Module": mod = getattr(mod, item) if not isinstance(mod, Module): - raise AttributeError("`" + item + "` is not an nn.Module") + raise TypeError("`" + item + "` is not an nn.Module") return mod def get_parameter(self, target: str): - module_path, _, param_name = target.rpartition(".") - - mod: Module = self.get_submodule(module_path) - - if not hasattr(mod, param_name): - raise AttributeError( - mod._get_name() + " has no attribute `" + param_name + "`" - ) - - param: Parameter = getattr(mod, param_name) - - if not isinstance(param, Parameter): - raise AttributeError("`" + param_name + "` is not an nn.Parameter") - - return param - - def get_buffer(self, target: str): - module_path, _, buffer_name = target.rpartition(".") - - mod: Module = self.get_submodule(module_path) - - if not hasattr(mod, buffer_name): - raise AttributeError( - mod._get_name() + " has no attribute `" + buffer_name + "`" - ) - - buffer: Tensor = getattr(mod, buffer_name) - - if buffer_name not in mod._buffers: - raise AttributeError("`" + buffer_name + "` is not a buffer") - - return buffer + target = target.replace(".", "/") + return self.v[target] def _named_members( self, get_members_fn, prefix="", recurse=True, remove_duplicate: bool = True @@ -311,22 +186,41 @@ def _named_members( for module_prefix, module in modules: members = get_members_fn(module) for k, v in members: - if v is None or v in memo: + if v is None or id(v) in memo: continue if remove_duplicate: - memo.add(v) + memo.add(id(v)) name = module_prefix + ("." if module_prefix else "") + k yield name, v def parameters(self, recurse: bool = True) -> Iterator[Parameter]: - for name, param in self.named_parameters(recurse=recurse): + 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._parameters.items(), + lambda module: module.v.items(), + prefix=prefix, + recurse=recurse, + remove_duplicate=remove_duplicate, + ) + yield from gen + + def named_buffers( + self, prefix: str = "", recurse: bool = True, remove_duplicate: bool = True + ) -> Iterator[Tuple[str, Tensor]]: + if not getattr(self, "_built", False): + self.build( + *self._args, dynamic_backend=self._dynamic_backend, **self._kwargs + ) + gen = self._named_members( + lambda module: module.buffers.items(), prefix=prefix, recurse=recurse, remove_duplicate=remove_duplicate, @@ -334,14 +228,18 @@ def named_parameters( yield from gen def children(self) -> Iterator["Module"]: - for name, module in self.named_children(): + 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._modules.items(): - if module is not None and module not in memo: - memo.add(module) + 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"]: @@ -354,30 +252,26 @@ def named_modules( 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 self not in memo: + if id(self) not in memo: if remove_duplicate: - memo.add(self) + memo.add(id(self)) yield prefix, self - for name, module in self._modules.items(): + 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 train(self, mode: bool = True): - if not isinstance(mode, bool): - raise ValueError("training mode is expected to be boolean") - self.training = mode - for module in self.children(): - module.train(mode) - return self - - def eval(self): - return self.train(False) + if not hasattr(module, "named_modules"): + yield submodule_prefix, self + else: + yield from module.named_modules( + memo, submodule_prefix, remove_duplicate + ) def requires_grad_(self, requires_grad: bool = True): for p in self.parameters(): @@ -387,351 +281,37 @@ def requires_grad_(self, requires_grad: bool = True): def _get_name(self): return self.__class__.__name__ - def extra_repr(self) -> str: + def _extra_repr(self) -> str: return "" - def register_full_backward_pre_hook( - self, - hook: Callable[["Module", _grad_t], Union[None, _grad_t]], - prepend: bool = False, - ) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle(self._backward_pre_hooks) - self._backward_pre_hooks[handle.id] = hook - if prepend: - self._backward_pre_hooks.move_to_end(handle.id, last=False) - return handle - - def register_backward_hook( - self, hook: Callable[["Module", _grad_t, _grad_t], Union[None, _grad_t]] - ) -> hooks.RemovableHandle: - if self._is_full_backward_hook is True: - raise RuntimeError( - "Cannot use both regular backward hooks and full backward hooks on a " - "single Module. Please use only one of them." - ) - - self._is_full_backward_hook = False - - handle = hooks.RemovableHandle(self._backward_hooks) - self._backward_hooks[handle.id] = hook - return handle - - def register_full_backward_hook( - self, - hook: Callable[["Module", _grad_t, _grad_t], Union[None, _grad_t]], - prepend: bool = False, - ) -> hooks.RemovableHandle: - if self._is_full_backward_hook is False: - raise RuntimeError( - "Cannot use both regular backward hooks and full backward hooks on a " - "single Module. Please use only one of them." - ) - - self._is_full_backward_hook = True - - handle = hooks.RemovableHandle(self._backward_hooks) - self._backward_hooks[handle.id] = hook - if prepend: - self._backward_hooks.move_to_end(handle.id, last=False) - return handle - - def _get_backward_hooks(self): - full_backward_hooks: List[Callable] = [] - if _global_is_full_backward_hook is True: - full_backward_hooks += _global_backward_hooks.values() - if self._is_full_backward_hook is True: - full_backward_hooks += self._backward_hooks.values() - - non_full_backward_hooks: List[Callable] = [] - if _global_is_full_backward_hook is False: - non_full_backward_hooks += _global_backward_hooks.values() - if self._is_full_backward_hook is False: - non_full_backward_hooks += self._backward_hooks.values() - - return full_backward_hooks, non_full_backward_hooks - - def _get_backward_pre_hooks(self): - backward_pre_hooks: List[Callable] = [] - backward_pre_hooks += _global_backward_pre_hooks.values() - backward_pre_hooks += self._backward_pre_hooks.values() - return backward_pre_hooks - - def _maybe_warn_non_full_backward_hook(self, inputs, result, grad_fn): - if not isinstance(result, Tensor): - if not ( - isinstance(result, tuple) and all(isinstance(r, Tensor) for r in result) - ): - warnings.warn( - "Using non-full backward hooks on a Module that does not return a" - " single Tensor or a tuple of Tensors is deprecated and will be" - " removed in future versions. This hook will be missing some of the" - " grad_output. Please use register_full_backward_hook to get the" - " documented behavior." - ) - return - else: - result = (result,) - - if not isinstance(inputs, Tensor): - if not ( - isinstance(inputs, tuple) and all(isinstance(i, Tensor) for i in inputs) - ): - warnings.warn( - "Using non-full backward hooks on a Module that does not take as" - " input a single Tensor or a tuple of Tensors is deprecated and" - " will be removed in future versions. This hook will be missing" - " some of the grad_input. Please use register_full_backward_hook to" - " get the documented behavior." - ) - return - else: - inputs = (inputs,) - - # At this point we are sure that inputs and result are tuple of Tensors - out_grad_fn = {r.grad_fn for r in result if r.grad_fn is not None} - if len(out_grad_fn) == 0 or ( - len(out_grad_fn) == 1 and grad_fn not in out_grad_fn - ): - warnings.warn( - "Using a non-full backward hook when outputs are nested in python data" - " structure is deprecated and will be removed in future versions. This" - " hook will be missing some grad_output." - ) - elif len(out_grad_fn) > 1: - warnings.warn( - "Using a non-full backward hook when outputs are generated by different" - " autograd Nodes is deprecated and will be removed in future versions." - " This hook will be missing some grad_output. Please use" - " register_full_backward_hook to get the documented behavior." - ) - else: - # At this point the grad_output part of the hook will most likely be correct - inputs_grad_fn = {i.grad_fn for i in inputs if i.grad_fn is not None} - - next_functions = {n[0] for n in grad_fn.next_functions} - - if inputs_grad_fn != next_functions: - warnings.warn( - "Using a non-full backward hook when the forward contains multiple" - " autograd Nodes is deprecated and will be removed in future" - " versions. This hook will be missing some grad_input. Please use" - " register_full_backward_hook to get the documented behavior." - ) - - def register_forward_pre_hook( - self, hook, *, prepend: bool = False, with_kwargs: bool = False - ) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle( - self._forward_pre_hooks, extra_dict=self._forward_pre_hooks_with_kwargs - ) - self._forward_pre_hooks[handle.id] = hook - if with_kwargs: - self._forward_pre_hooks_with_kwargs[handle.id] = True - - if prepend: - self._forward_pre_hooks.move_to_end(handle.id, last=False) - return handle - - def register_forward_hook( - self, - hook, - *, - prepend: bool = False, - with_kwargs: bool = False, - always_call: bool = False, - ) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle( - self._forward_hooks, - extra_dict=[ - self._forward_hooks_with_kwargs, - self._forward_hooks_always_called, - ], - ) - self._forward_hooks[handle.id] = hook - if with_kwargs: - self._forward_hooks_with_kwargs[handle.id] = True - if always_call: - self._forward_hooks_always_called[handle.id] = True - if prepend: - self._forward_hooks.move_to_end(handle.id, last=False) - return handle - - def _wrapped_call_impl(self, *args, **kwargs): - if self._compiled_call_impl is not None: - return self._compiled_call_impl(*args, **kwargs) - else: - return self._call_impl(*args, **kwargs) - def _call_impl(self, *args, **kwargs): - forward_call = self.forward - # If we don't have any hooks, we want to skip the rest of the logic in - # this function, and just call forward. - if not ( - self._backward_hooks - or self._backward_pre_hooks - or self._forward_hooks - or self._forward_pre_hooks - or _global_backward_pre_hooks - or _global_backward_hooks - or _global_forward_hooks - or _global_forward_pre_hooks - ): - return forward_call(*args, **kwargs) - - try: - result = None - called_always_called_hooks = set() - - full_backward_hooks, non_full_backward_hooks = [], [] - backward_pre_hooks = [] - if self._backward_pre_hooks or _global_backward_pre_hooks: - backward_pre_hooks = self._get_backward_pre_hooks() - - if self._backward_hooks or _global_backward_hooks: - full_backward_hooks, non_full_backward_hooks = ( - self._get_backward_hooks() - ) - - if _global_forward_pre_hooks or self._forward_pre_hooks: - for hook_id, hook in ( - *_global_forward_pre_hooks.items(), - *self._forward_pre_hooks.items(), - ): - if hook_id in self._forward_pre_hooks_with_kwargs: - args_kwargs_result = hook(self, args, kwargs) - if args_kwargs_result is not None: - if ( - isinstance(args_kwargs_result, tuple) - and len(args_kwargs_result) == 2 - ): - args, kwargs = args_kwargs_result - else: - raise RuntimeError( - "forward pre-hook must return None or a tuple of" - " (new_args, new_kwargs), but got" - f" {args_kwargs_result}." - ) - else: - args_result = hook(self, args) - if args_result is not None: - if not isinstance(args_result, tuple): - args_result = (args_result,) - args = args_result - - bw_hook = None - if full_backward_hooks or backward_pre_hooks: - bw_hook = hooks.BackwardHook( - self, full_backward_hooks, backward_pre_hooks - ) - args = bw_hook.setup_input_hook(args) - - result = forward_call(*args, **kwargs) - if _global_forward_hooks or self._forward_hooks: - for hook_id, hook in ( - *_global_forward_hooks.items(), - *self._forward_hooks.items(), - ): - # mark that always called hook is run - if ( - hook_id in self._forward_hooks_always_called - or hook_id in _global_forward_hooks_always_called - ): - called_always_called_hooks.add(hook_id) - - if hook_id in self._forward_hooks_with_kwargs: - hook_result = hook(self, args, kwargs, result) - else: - hook_result = hook(self, args, result) - - if hook_result is not None: - result = hook_result - - if bw_hook: - if not isinstance(result, (Tensor, tuple)): - warnings.warn( - "For backward hooks to be called," - " module output should be a Tensor or a tuple of Tensors" - f" but received {type(result)}" - ) - result = bw_hook.setup_output_hook(result) - - # Handle the non-full backward hooks - if non_full_backward_hooks: - var = result - while not isinstance(var, Tensor): - if isinstance(var, dict): - var = next(v for v in var.values() if isinstance(v, Tensor)) - else: - var = var[0] - grad_fn = var.grad_fn - if grad_fn is not None: - for hook in non_full_backward_hooks: - grad_fn.register_hook(_WrappedHook(hook, self)) - self._maybe_warn_non_full_backward_hook(args, result, grad_fn) - - return result - - except Exception: - # run always called hooks if they have not already been run - # For now only forward hooks have the always_call option but perhaps - # this functionality should be added to full backward hooks as well. - for hook_id, hook in _global_forward_hooks.items(): - if ( - hook_id in _global_forward_hooks_always_called - and hook_id not in called_always_called_hooks - ): - try: - hook_result = hook(self, args, result) - if hook_result is not None: - result = hook_result - except Exception as e: - warnings.warn( - "global module forward hook with ``always_call=True``" - " raised an exception that was silenced as another error" - f" was raised in forward: {str(e)}" - ) - continue - - for hook_id, hook in self._forward_hooks.items(): - if ( - hook_id in self._forward_hooks_always_called - and hook_id not in called_always_called_hooks - ): - try: - if hook_id in self._forward_hooks_with_kwargs: - hook_result = hook(self, args, kwargs, result) - else: - hook_result = hook(self, args, result) - if hook_result is not None: - result = hook_result - except Exception as e: - warnings.warn( - "module forward hook with ``always_call=True`` raised an" - " exception that was silenced as another error was raised" - f" in forward: {str(e)}" - ) - continue - # raise exception raised in try block - raise + return self.call(*args, **kwargs) def __getattribute__(self, name: str) -> Any: - if name in ("__dict__", "v", "buffers"): - return super(Module, self).__getattribute__(name) - if "_parameters" in self.__dict__: - _parameters = self.__dict__["_parameters"] - if name in _parameters: - return _parameters[name] - if "_buffers" in self.__dict__: - _buffers = self.__dict__["_buffers"] - if name in _buffers: - return _buffers[name] - if "_modules" in self.__dict__: - modules = self.__dict__["_modules"] + 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] - return super(Module, self).__getattribute__(name) - - def __setattr__(self, name: str, value: Union[Tensor, "Module"]) -> None: + 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: @@ -740,96 +320,25 @@ def remove_from(*dicts_or_sets): else: d.discard(name) - params = self.__dict__.get("_parameters") - if isinstance(value, Parameter): - if params is None: - raise AttributeError( - "cannot assign parameters before Module.__init__() call" - ) - remove_from( - self.__dict__, - self._buffers, - self._modules, - self._non_persistent_buffers_set, - ) + 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: - modules = self.__dict__.get("_modules") - if isinstance(value, Module): - if modules is None: - raise AttributeError( - "cannot assign module before Module.__init__() call" - ) - remove_from( - self.__dict__, - self._parameters, - self._buffers, - self._non_persistent_buffers_set, - ) - for hook in _global_module_registration_hooks.values(): - output = hook(self, name, value) - if output is not None: - value = output - modules[name] = value - elif modules is not None and name in modules: - if value is not None: - raise TypeError( - f"cannot assign '{type(value)}' as child module '{name}' " - "(torch.nn.Module or None expected)" - ) - for hook in _global_module_registration_hooks.values(): - output = hook(self, name, value) - if output is not None: - value = output - modules[name] = value - else: - buffers = self.__dict__.get("_buffers") - if buffers is not None and name in buffers: - if value is not None and not isinstance(value, Tensor): - raise TypeError( - f"cannot assign '{type(value)}' as buffer '{name}' " - "(torch.Tensor or None expected)" - ) - for hook in _global_buffer_registration_hooks.values(): - output = hook(self, name, value) - if output is not None: - value = output - buffers[name] = value - else: - super().__setattr__(name, value) - - def __delattr__(self, name): - if name in self._parameters: - del self._parameters[name] - elif name in self._buffers: - del self._buffers[name] - self._non_persistent_buffers_set.discard(name) - elif name in self._modules: - del self._modules[name] - else: - super().__delattr__(name) - - def _register_state_dict_hook(self, hook): - handle = hooks.RemovableHandle(self._state_dict_hooks) - self._state_dict_hooks[handle.id] = hook - return handle - - def register_state_dict_pre_hook(self, hook): - handle = hooks.RemovableHandle(self._state_dict_pre_hooks) - self._state_dict_pre_hooks[handle.id] = hook - return handle + 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() + 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._modules.items(): + for key, module in self._module_dict.items(): mod_str = repr(module) - mod_str = _addindent(mod_str, 2) + mod_str = self._addindent(mod_str, 2) child_lines.append("(" + key + "): " + mod_str) lines = extra_lines + child_lines @@ -847,8 +356,8 @@ def __repr__(self): def __dir__(self): module_attrs = dir(self.__class__) attrs = list(self.__dict__.keys()) - parameters = list(self._parameters.keys()) - modules = list(self._modules.keys()) + parameters = list(self._v.keys()) + modules = list(self._module_dict.keys()) buffers = list(self._buffers.keys()) keys = module_attrs + attrs + parameters + modules + buffers @@ -857,128 +366,14 @@ def __dir__(self): return sorted(keys) - -# --- 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 - - -# --- Main --- # -# ------------ # - - -def register_module_backward_hook( - hook: Callable[["Module", _grad_t, _grad_t], Union[None, _grad_t]] -) -> hooks.RemovableHandle: - global _global_is_full_backward_hook - if _global_is_full_backward_hook is True: - raise RuntimeError( - "Cannot use both regular backward hooks and full backward hooks as a " - "global Module hook. Please use only one of them." - ) - - _global_is_full_backward_hook = False - - handle = hooks.RemovableHandle(_global_backward_hooks) - _global_backward_hooks[handle.id] = hook - return handle - - -def register_module_buffer_registration_hook( - hook: Callable[..., None] -) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle(_global_buffer_registration_hooks) - _global_buffer_registration_hooks[handle.id] = hook - return handle - - -def register_module_forward_hook( - hook: Callable[..., None], *, always_call: bool = False -) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle( - _global_forward_hooks, extra_dict=_global_forward_hooks_always_called - ) - _global_forward_hooks[handle.id] = hook - if always_call: - _global_forward_hooks_always_called[handle.id] = True - return handle - - -def register_module_forward_pre_hook( - hook: Callable[..., None] -) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle(_global_forward_pre_hooks) - _global_forward_pre_hooks[handle.id] = hook - return handle - - -def register_module_full_backward_hook( - hook: Callable[["Module", _grad_t, _grad_t], Union[None, _grad_t]] -) -> hooks.RemovableHandle: - global _global_is_full_backward_hook - if _global_is_full_backward_hook is False: - raise RuntimeError( - "Cannot use both regular backward hooks and full backward hooks as a " - "global Module hook. Please use only one of them." - ) - - _global_is_full_backward_hook = True - - handle = hooks.RemovableHandle(_global_backward_hooks) - _global_backward_hooks[handle.id] = hook - return handle - - -def register_module_full_backward_pre_hook( - hook: Callable[["Module", _grad_t], Union[None, _grad_t]] -) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle(_global_backward_pre_hooks) - _global_backward_pre_hooks[handle.id] = hook - return handle - - -def register_module_module_registration_hook( - hook: Callable[..., None] -) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle(_global_module_registration_hooks) - _global_module_registration_hooks[handle.id] = hook - return handle - - -def register_module_parameter_registration_hook( - hook: Callable[..., None] -) -> hooks.RemovableHandle: - handle = hooks.RemovableHandle(_global_parameter_registration_hooks) - _global_parameter_registration_hooks[handle.id] = hook - return handle - - -r"""This tracks hooks common to all modules that are executed immediately before -.registering the buffer/module/parameter""" -_global_buffer_registration_hooks: Dict[int, Callable] = OrderedDict() -_global_module_registration_hooks: Dict[int, Callable] = OrderedDict() -_global_parameter_registration_hooks: Dict[int, Callable] = OrderedDict() -r""" -This tracks hooks common to all modules that are executed before/after calling forward -and backward. - -This is global state used for debugging/profiling purposes -""" -_global_backward_pre_hooks: Dict[int, Callable] = OrderedDict() -_global_backward_hooks: Dict[int, Callable] = OrderedDict() -_global_is_full_backward_hook: Optional[bool] = None -_global_forward_pre_hooks: Dict[int, Callable] = OrderedDict() -_global_forward_hooks: Dict[int, Callable] = OrderedDict() -_global_forward_hooks_always_called: Dict[int, bool] = OrderedDict() + def __getstate__(self): + state = self.__dict__.copy() + state.pop("_compiled_call_impl", None) + state.pop("_thread_local", None) + state.pop("_metrics_lock", None) + return state + + def __setstate__(self, state): + state["_thread_local"] = threading.local() + state["_metrics_lock"] = threading.Lock() + self.__dict__.update(state) diff --git a/ivy/functional/frontends/torch/pointwise_ops.py b/ivy/functional/frontends/torch/pointwise_ops.py index ed698fccf6bd9..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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 4b3b21bad1160..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.1 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.1 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.1 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.1 and below": ( + "2.2 and below": ( "float32", "float64", ) @@ -95,7 +95,7 @@ def rand( 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 @@ -195,7 +195,7 @@ def randn( 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 6870cbece2f72..58f84c3fba7b0 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.1 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.1 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.1 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: @@ -119,14 +135,26 @@ def max(*input, dim=None, keepdim=False, out=None): @numpy_to_torch_style_args @to_ivy_arrays_and_back -def mean(input, dim=None, keepdim=False, *, dtype=None, out=None): +@with_supported_dtypes( + { + "2.2.1 and below": ( + "bfloat16", + "float16", + "float32", + "float64", + "complex64", + "complex128", + ) + }, + "torch", +) +def mean(input, /, dim=None, keepdim=False, *, dtype=None, out=None): if dtype is not None: - input = input.astype(dtype) - if out is not None: - out = out.astype(dtype) - return ivy.mean(input, axis=dim, keepdims=keepdim, out=out) + dtype = ivy.as_native_dtype(dtype) + return ivy.mean(input, axis=dim, keepdims=keepdim, dtype=dtype, 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): @@ -163,14 +191,24 @@ def median(input, dim=None, keepdim=False, *, out=None): @numpy_to_torch_style_args @to_ivy_arrays_and_back @with_unsupported_dtypes( - {"2.1.1 and below": ("complex64", "complex128")}, + {"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: @@ -190,6 +228,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): @@ -234,7 +273,7 @@ def nanmedian(input, dim=None, keepdim=False, *, out=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 and below": ("float", "int")}, + {"2.2 and below": ("float", "int")}, "torch", ) def nansum(input, dim=None, keepdim=False, *, dtype=None): @@ -244,7 +283,7 @@ def nansum(input, dim=None, keepdim=False, *, dtype=None): @to_ivy_arrays_and_back @with_supported_dtypes( - {"2.1.1 and below": ("float", "complex")}, + {"2.2 and below": ("float", "complex")}, "torch", ) def norm(input, p="fro", dim=None, keepdim=False, out=None, dtype=None): @@ -270,7 +309,7 @@ def norm(input, p="fro", dim=None, keepdim=False, out=None, dtype=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -286,7 +325,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.1 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 @@ -295,14 +334,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.1 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.1 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 @@ -317,37 +356,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.1 and below": ( + "2.2 and below": ( "float16", "complex", ) @@ -355,7 +383,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: @@ -369,7 +397,7 @@ def unique_consecutive(input, return_inverse, return_counts, dim): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -384,7 +412,7 @@ def var(input, dim, unbiased, keepdim=False, *, out=None): @to_ivy_arrays_and_back @with_unsupported_dtypes( { - "2.1.1 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/tensor.py b/ivy/functional/frontends/torch/tensor.py index bf7ab631a2628..d27360e361468 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, @@ -47,6 +47,12 @@ def __repr__(self): def __hash__(self): return id(self) + def __setattr__(self, name, value): + if name == "data": + self.ivy_array = value.ivy_array + else: + super().__setattr__(name, value) + # Properties # # ---------- # @@ -84,6 +90,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( @@ -137,7 +147,7 @@ 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: @@ -145,20 +155,20 @@ def reshape(self, *args, shape=None): else: raise ValueError("reshape() got no values for argument 'shape'") - @with_unsupported_dtypes({"2.1.1 and below": ("bfloat16",)}, "torch") - @with_unsupported_dtypes({"2.5.1 and below": ("float16",)}, "paddle") + @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.1 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.1 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.1 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) @@ -173,111 +183,113 @@ 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 + def float_power(self, exponent): + return torch_frontend.float_power(self, exponent) + @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 @@ -285,6 +297,7 @@ def view(self, *args, size=None): - list of ints - torch.Size object - ints + Parameters ---------- args:int arguments @@ -297,7 +310,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] @@ -317,56 +330,56 @@ def float(self, memory_format=None): def double(self): return self.to(torch_frontend.float64) - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 @@ -374,31 +387,31 @@ def copy_(self, other, non_blocking=False): self._ivy_array = torch_frontend.tensor(other).ivy_array return self - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 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) @@ -409,7 +422,7 @@ def abs_(self): self.ivy_array = self.abs().ivy_array return self - @with_unsupported_dtypes({"2.1.1 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) @@ -420,24 +433,28 @@ def logical_not_(self): self.ivy_array = ivy.astype(self.logical_not().ivy_array, self.dtype) return self - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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 @@ -460,18 +477,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.1 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.1 and below": ( + "2.2 and below": ( "bfloat16", "uint8", "uint32", @@ -488,7 +509,7 @@ def not_equal(self, other, *, out=None): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "uint8", "uint32", @@ -504,20 +525,38 @@ 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.1 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.1 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) + + @with_supported_device_and_dtypes( + {"2.2 and below": {"cpu": ("float32", "float64")}}, + "torch", + ) + def erfc_(self, *, out=None): + self.ivy_array = self.erfc(out=out).ivy_array + return self + def new_zeros( self, *args, @@ -541,34 +580,27 @@ def new_zeros( ) def to(self, *args, **kwargs): - if len(args) > 0: - if hasattr(args[0], "ivy_array") or ivy.is_array(args[0]): - if self.dtype == ivy.dtype(args[0]) and self.device == ivy.dev(args[0]): - return self - else: - cast_tensor = self.clone() - cast_tensor.ivy_array = ivy.asarray( - self.ivy_array, - dtype=ivy.dtype(args[0]), - device=ivy.dev(args[0]), - ) - return cast_tensor - if ( - isinstance(args[0], (ivy.Dtype, ivy.NativeDtype)) - or args[0] in ivy._all_ivy_dtypes_str + device = None + dtype = None + + # look for device and dtype in the args + for arg in args: + if hasattr(arg, "ivy_array") or ivy.is_array(arg): + device = ivy.dev(arg) + dtype = ivy.dtype(arg) + elif ( + isinstance(arg, ivy.NativeDtype) + or isinstance(arg, ivy.Dtype) + and hasattr(arg, "as_native_dtype") + or arg in ivy._all_ivy_dtypes_str ): - if self.dtype == ivy.as_ivy_dtype(args[0]): - return self - else: - cast_tensor = self.clone() - cast_tensor.ivy_array = ivy.asarray(self.ivy_array, dtype=args[0]) - return cast_tensor - if isinstance(args[0], (ivy.Device, ivy.NativeDevice, str)): - if isinstance(args[0], str) and not isinstance( - args[0], (ivy.Device, ivy.NativeDevice) + dtype = arg + elif isinstance(arg, (ivy.Device, ivy.NativeDevice, str)): + if isinstance(arg, str) and not isinstance( + arg, (ivy.Device, ivy.NativeDevice) ): ivy.utils.assertions.check_elem_in_list( - args[0], + arg, [ "cpu", "cuda", @@ -589,34 +621,32 @@ def to(self, *args, **kwargs): "hpu", ], ) - if self.device == ivy.as_ivy_dev(args[0]): - return self - else: - cast_tensor = self.clone() - cast_tensor.ivy_array = ivy.asarray(self.ivy_array, device=args[0]) - return cast_tensor + device = arg + + # look for device and dtype in the kwargs + if "device" in kwargs: + device = kwargs["device"] + if "dtype" in kwargs: + dtype = kwargs["dtype"] + + if (dtype is None or self.dtype == dtype) and ( + device is None or self.device == ivy.as_ivy_dev(device) + ): + return self else: - if ( - "dtype" in kwargs - and "device" in kwargs - and self.dtype == kwargs["dtype"] - and self.device == kwargs["device"] - ): - return self - else: - cast_tensor = self.clone() - cast_tensor.ivy_array = ivy.asarray( - self.ivy_array, - device=kwargs["device"] if "device" in kwargs else self.device, - dtype=kwargs["dtype"] if "dtype" in kwargs else self.dtype, - ) - return cast_tensor - - @with_unsupported_dtypes({"2.1.1 and below": ("float16",)}, "torch") + cast_tensor = self.clone() + cast_tensor.ivy_array = ivy.asarray( + self.ivy_array, + dtype=dtype, + device=device, + ) + return cast_tensor + + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def acos(self): return torch_frontend.acos(self) - @with_unsupported_dtypes({"2.1.1 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 @@ -636,7 +666,7 @@ def new_tensor( _data = ivy.asarray(data, copy=True, dtype=dtype, device=device) return torch_frontend.tensor(_data) - @with_unsupported_dtypes({"2.1.1 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def view_as(self, other): return self.view(size=other.shape) @@ -644,11 +674,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): @@ -665,7 +698,7 @@ def detach_(self): self.ivy_array = self.detach().ivy_array return self - @with_unsupported_dtypes({"2.1.1 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) @@ -739,9 +772,23 @@ 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 + if dimension == -1: + new_shape.insert(dimension, size) + else: + 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) @@ -753,7 +800,7 @@ def max(self, dim=None, keepdim=False): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "complex", "bfloat16", "bool", @@ -779,36 +826,39 @@ def is_cuda(self): def is_meta(self): return "meta" in ivy.dev(self.ivy_array) - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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) @@ -817,20 +867,20 @@ def argwhere(self): return torch_frontend.argwhere(self) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def ceil(self): return torch_frontend.ceil(self) @@ -844,7 +894,7 @@ 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: @@ -853,22 +903,22 @@ def permute(self, *args, dims=None): raise ValueError("permute() got no values for argument 'dims'") @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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) @@ -886,35 +936,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.1 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.1 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=dtype).ivy_array return self - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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 @@ -934,10 +989,10 @@ def type(self, dtype=None, non_blocking=False, **kwargs): else: return str(self.dtype) - @with_unsupported_dtypes({"2.1.1 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): @@ -949,7 +1004,7 @@ def squeeze(self, dim=None): return torch_frontend.squeeze(self, dim) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.1 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 @@ -973,35 +1028,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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 @@ -1012,51 +1071,72 @@ 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.1 and below": ("float16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16",)}, "torch") def acosh(self): return torch_frontend.acosh(self) def masked_fill(self, mask, value): + dtype = ivy.as_native_dtype(self.dtype) return torch_frontend.tensor( - torch_frontend.where(mask, value, self), dtype=self.dtype + ivy.astype(torch_frontend.where(mask, value, self), dtype) ) def masked_fill_(self, mask, value): self.ivy_array = self.masked_fill(mask, value).ivy_array return self - @with_unsupported_dtypes({"2.1.1 and below": ("float16", "bfloat16")}, "torch") + def masked_select(self, mask): + return torch_frontend.masked_select(self, mask) + + def masked_scatter(self, mask, source): + flat_self = torch_frontend.flatten(self.clone()) + flat_mask = torch_frontend.flatten(mask) + flat_source = torch_frontend.flatten(source) + indices = torch_frontend.squeeze(torch_frontend.nonzero(flat_mask), -1) + flat_self.scatter_(0, indices, flat_source[: indices.shape[0]]) + return flat_self.reshape(self.shape) + + def masked_scatter_(self, mask, source): + flat_self = torch_frontend.flatten(self.clone()) + flat_mask = torch_frontend.flatten(mask) + flat_source = torch_frontend.flatten(source) + indices = torch_frontend.squeeze(torch_frontend.nonzero(flat_mask), -1) + flat_self.scatter_(0, indices, flat_source[: indices.shape[0]]) + self.ivy_array = flat_self.reshape(self.shape).ivy_array + return self + + @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.1 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.1 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.1 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.1 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.1 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.1 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) @@ -1069,7 +1149,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 @@ -1088,7 +1168,7 @@ def remainder(self, other, *, out=None): return torch_frontend.remainder(self, other, out=out) @with_supported_dtypes( - {"2.1.1 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 @@ -1106,35 +1186,42 @@ def bitwise_and_(self, other): self.ivy_array = self.bitwise_and(other).ivy_array return self - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 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 @@ -1145,11 +1232,11 @@ def isinf(self): def is_complex(self): return torch_frontend.is_complex(self._ivy_array) - @with_unsupported_dtypes({"2.1.1 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.1 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def isreal(self): return torch_frontend.isreal(self._ivy_array) @@ -1160,38 +1247,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.1 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.1 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.1 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.1 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.1 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.1 and below": ("bfloat16",)}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("bfloat16",)}, "torch") def __rpow__(self, other): return torch_frontend.pow(other, self) @@ -1213,30 +1311,41 @@ def __iter__(self): for i in range(self.shape[0]): yield self[i] - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 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) @@ -1291,45 +1400,52 @@ def __float__(self): item = item.real return float(item) - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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) @@ -1350,15 +1466,20 @@ def bitwise_xor_(self, other): def item(self): if all(dim == 1 for dim in self.shape): - return self.ivy_array.to_scalar() + if ivy.current_backend_str() == "tensorflow": + import tensorflow as tf + + return tf.squeeze(self.ivy_array.data) + else: + return self.ivy_array.to_scalar() else: raise ValueError( "only one element tensors can be converted to Python scalars" ) @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.1 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 @@ -1370,26 +1491,26 @@ def cov(self, /, *, correction=1, fweights=None, aweights=None): self, correction=correction, fweights=fweights, aweights=aweights ) - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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 @@ -1398,33 +1519,33 @@ def exp_(self): def mul(self, other): return torch_frontend.mul(self, other) - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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.1 and below": ("float16", "bfloat16")}, "torch") + @with_unsupported_dtypes({"2.2 and below": ("float16", "bfloat16")}, "torch") def det(self): return torch_frontend.det(self) @@ -1432,9 +1553,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): @@ -1443,13 +1565,13 @@ def nonzero(self, as_tuple=False): def mm(self, mat2): return torch_frontend.mm(self, mat2) - @with_unsupported_dtypes({"2.1.1 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.1 and below": ( + "2.2 and below": ( "float16", "float32", "float64", @@ -1468,18 +1590,19 @@ def square_(self): self.ivy_array = torch_frontend.square(self._ivy_array).ivy_array return self - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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): @@ -1487,7 +1610,7 @@ def short(self, memory_format=None): return self @numpy_to_torch_style_args - @with_unsupported_dtypes({"2.1.1 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) @@ -1499,7 +1622,7 @@ def div_(self, other, *, rounding_mode=None): return self @with_supported_dtypes( - {"2.1.1 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 @@ -1515,26 +1638,26 @@ def normal_(self, mean=0, std=1, *, generator=None): ) return self - @with_unsupported_dtypes({"2.1.1 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.1 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.1 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.1 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.1 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 @@ -1545,11 +1668,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.1 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.1 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 @@ -1560,96 +1683,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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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.1 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 @@ -1678,16 +1801,18 @@ def stride(self, dim=None): return strides @with_supported_dtypes( - {"2.1.1 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.1 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): @@ -1704,14 +1829,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.1 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.1 and below": ( + "2.2 and below": ( "bfloat16", "complex", "float64", @@ -1727,7 +1852,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.1 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) @@ -1735,14 +1860,14 @@ def gather(self, dim, index): return torch_frontend.gather(self, dim=dim, index=index) @with_supported_dtypes( - {"2.1.1 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.1 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: @@ -1759,7 +1884,7 @@ def scatter_(self, dim, index, src, *, reduce=None): return self @with_supported_dtypes( - {"2.1.1 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": @@ -1770,19 +1895,19 @@ def scatter_reduce_(self, dim, index, src, reduce, *, include_self=True): return self @with_supported_dtypes( - {"2.1.1 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.1 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.1 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) @@ -1793,14 +1918,25 @@ 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.1 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.1 and below": ("bfloat16", "float16")}, "torch") + @with_supported_dtypes( + { + "2.2 and below": ( + "float32", + "float64", + "complex32", + "complex64", + "complex128", + ) + }, + "torch", + ) def cholesky(self, upper=False): return torch_frontend.cholesky(self, upper=upper) @@ -1815,7 +1951,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 @@ -1839,10 +1975,15 @@ def backward(self, gradient=None, retain_graph=None, create_graph=False): else: next_function(_grad_list[idx]) - @with_unsupported_dtypes({"2.1.1 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) @@ -1863,17 +2004,17 @@ def adjoint(self): return torch_frontend.adjoint(self) @with_unsupported_dtypes( - {"2.1.1 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.1 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.1 and below": ("float16", "bfloat16", "float32", "float64", "complex")}, + {"2.2 and below": ("float16", "bfloat16", "float32", "float64", "complex")}, "torch", ) def gcd(self, other, *, out=None): @@ -1881,7 +2022,7 @@ def gcd(self, other, *, out=None): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", "uint16", @@ -1901,7 +2042,7 @@ def char(self): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", "float32", @@ -1918,7 +2059,7 @@ def lcm(self, other, *, out=None): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", "float32", @@ -1939,7 +2080,7 @@ def lcm_(self, other, *, out=None): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "int8", "uint8", @@ -1956,7 +2097,7 @@ def triu_(self, diagonal=0): return self @with_unsupported_dtypes( - {"2.1.1 and below": ("float16", "bfloat16")}, + {"2.2 and below": ("float16", "bfloat16")}, "torch", ) def quantile(self, q, dim=None, keepdim=False, *, interpolation="linear", out=None): @@ -1966,7 +2107,7 @@ def quantile(self, q, dim=None, keepdim=False, *, interpolation="linear", out=No @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "int8", "int16", "uint8", @@ -1998,7 +2139,7 @@ def random_( @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "integer", "unsigned", "bfloat16", @@ -2017,9 +2158,13 @@ def uniform_(self, from_=0, to=1, *, generator=None): ) 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.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -2031,7 +2176,7 @@ def sinc(self): @with_supported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float32", "float64", "bfloat16", @@ -2043,7 +2188,7 @@ def sinc_(self): self.ivy_array = torch_frontend.sinc(self).ivy_array return self - @with_unsupported_dtypes({"2.1.1 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 @@ -2052,7 +2197,7 @@ def index_fill(self, dim, index, value): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "int8", "uint8", @@ -2075,7 +2220,7 @@ def unique_consecutive(self, return_inverse, return_counts, dim): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "uint16", "uint32", "uint64", @@ -2092,7 +2237,7 @@ def cummax(self, dim): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "int8", "uint8", @@ -2110,7 +2255,7 @@ def triu(self, diagonal=0): return torch_frontend.triu(self, diagonal) @with_unsupported_dtypes( - {"2.1.1 and below": ("bfloat16",)}, + {"2.2 and below": ("bfloat16",)}, "torch", ) def xlogy_(self, *, other, out=None): @@ -2119,7 +2264,7 @@ def xlogy_(self, *, other, out=None): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "uint8", "uint32", @@ -2136,7 +2281,7 @@ def ne(self, other): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "uint8", "uint32", @@ -2153,7 +2298,7 @@ def ne_(self, other): @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "bfloat16", "int8", "uint8", @@ -2164,6 +2309,7 @@ def ne_(self, other): "float16", "complex128", "complex64", + "bool", ) }, "torch", @@ -2173,7 +2319,7 @@ def unique(self, sorted=True, return_inverse=False, return_counts=False, dim=Non @with_unsupported_dtypes( { - "2.1.1 and below": ( + "2.2 and below": ( "float16", "bfloat16", ) @@ -2183,27 +2329,64 @@ 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.1 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) + def fill_diagonal_(self, fill_value, wrap=False): + self._ivy_array = ivy.fill_diagonal(self._ivy_array, fill_value, wrap=wrap) + return self + @with_supported_dtypes( - {"2.1.1 and below": "valid"}, + {"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 @@ -2230,6 +2413,7 @@ def corrcoef(self): 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): @@ -2237,11 +2421,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}") + 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: + 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): @@ -2250,3 +2437,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 792e1f2d20c17..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.1 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.1 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.1 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 4ec08129df43e..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.1 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/torch/utils/__init__.py b/ivy/functional/frontends/torch/utils/__init__.py deleted file mode 100644 index 88be3837977fe..0000000000000 --- a/ivy/functional/frontends/torch/utils/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import hooks diff --git a/ivy/functional/frontends/torch/utils/hooks.py b/ivy/functional/frontends/torch/utils/hooks.py deleted file mode 100644 index dccc79e3560ce..0000000000000 --- a/ivy/functional/frontends/torch/utils/hooks.py +++ /dev/null @@ -1,231 +0,0 @@ -import torch -from collections import OrderedDict -import weakref -from typing import Any, Tuple - - -class RemovableHandle: - id: int - next_id: int = 0 - - def __init__(self, hooks_dict: Any, *, extra_dict: Any = None) -> None: - self.hooks_dict_ref = weakref.ref(hooks_dict) - self.id = RemovableHandle.next_id - RemovableHandle.next_id += 1 - - self.extra_dict_ref: Tuple = () - if isinstance(extra_dict, dict): - self.extra_dict_ref = (weakref.ref(extra_dict),) - elif isinstance(extra_dict, list): - self.extra_dict_ref = tuple(weakref.ref(d) for d in extra_dict) - - def remove(self) -> None: - hooks_dict = self.hooks_dict_ref() - if hooks_dict is not None and self.id in hooks_dict: - del hooks_dict[self.id] - - for ref in self.extra_dict_ref: - extra_dict = ref() - if extra_dict is not None and self.id in extra_dict: - del extra_dict[self.id] - - def __getstate__(self): - if self.extra_dict_ref is None: - return (self.hooks_dict_ref(), self.id) - else: - return ( - self.hooks_dict_ref(), - self.id, - tuple(ref() for ref in self.extra_dict_ref), - ) - - def __setstate__(self, state) -> None: - if state[0] is None: - # create a dead reference - self.hooks_dict_ref = weakref.ref(OrderedDict()) - else: - self.hooks_dict_ref = weakref.ref(state[0]) - self.id = state[1] - RemovableHandle.next_id = max(RemovableHandle.next_id, self.id + 1) - - if len(state) < 3 or state[2] is None: - self.extra_dict_ref = () - else: - self.extra_dict_ref = tuple(weakref.ref(d) for d in state[2]) - - def __enter__(self) -> "RemovableHandle": - return self - - def __exit__(self, type: Any, value: Any, tb: Any) -> None: - self.remove() - - -class BackwardHook: - def __init__(self, module, user_hooks, user_pre_hooks): - self.user_hooks = user_hooks - self.user_pre_hooks = user_pre_hooks - self.module = module - - self.grad_outputs = None - self.n_outputs = -1 - self.output_tensors_index = None - self.n_inputs = -1 - self.input_tensors_index = None - - def _pack_with_none(self, indices, values, size): - res = [None] * size - for idx, val in zip(indices, values): - res[idx] = val - - return tuple(res) - - def _unpack_none(self, indices, values): - res = [] - for idx in indices: - res.append(values[idx]) - - return tuple(res) - - def _set_user_hook(self, grad_fn): - def hook(grad_input, _): - if self.grad_outputs is None: - # This happens because the gradient in your nn.Module flows to - # the Module's input without " passing through the Module's - # output, e.g. when you're doing double backward. - return - res = self._pack_with_none( - self.input_tensors_index, grad_input, self.n_inputs - ) - - for hook in self.user_hooks: - out = hook(self.module, res, self.grad_outputs) - - if out is None: - continue - - if len(out) != len(res): - raise RuntimeError( - "Backward hook returned an invalid number of grad_input, " - f"got {len(out)}, but expected {len(res)}" - ) - - res = out - - self.grad_outputs = None - - return self._unpack_none(self.input_tensors_index, res) - - grad_fn.register_hook(hook) - - def _apply_on_tensors(self, fn, args): - # Can be used to apply the given function to the tensors contained in the - # args. Will return updated args and the tensors indices - tensors_idx = [] - tensors = [] - - requires_grad = False - for i, arg in enumerate(args): - if isinstance(arg, torch.Tensor): - tensors_idx.append(i) - tensors.append(arg) - requires_grad |= arg.requires_grad - - if not (requires_grad and torch.is_grad_enabled()): - return args, None - - new_tensors = torch.nn.modules._functions.BackwardHookFunction.apply(*tensors) - if len(new_tensors) == 0: - raise RuntimeError( - "Cannot set Module backward hook for a Module with no input Tensors." - ) - - grad_fns = [ - t.grad_fn - for t in new_tensors - if t.grad_fn is not None - and t.grad_fn.name() == "BackwardHookFunctionBackward" - ] - if len(grad_fns) == 0: - raise RuntimeError( - "Error while setting up backward hooks. Please open " - "an issue with a code sample to reproduce this." - ) - - fn(grad_fns[0]) - - arg_list = list(args) - for idx, val in zip(tensors_idx, new_tensors): - arg_list[idx] = val - - return tuple(arg_list), tensors_idx - - def setup_input_hook(self, args): - def fn(grad_fn): - self._set_user_hook(grad_fn) - - res, input_idx = self._apply_on_tensors(fn, args) - self.n_inputs = len(args) - self.input_tensors_index = input_idx - return res - - def setup_output_hook(self, args): - def fn(grad_fn): - def hook(_, grad_output): - self.grad_outputs = self._pack_with_none( - self.output_tensors_index, grad_output, self.n_outputs - ) - - if self.user_pre_hooks: - expected_len = len(self.grad_outputs) - for user_pre_hook in self.user_pre_hooks: - hook_grad_outputs = user_pre_hook( - self.module, self.grad_outputs - ) - if hook_grad_outputs is None: - continue - - actual_len = len(hook_grad_outputs) - if actual_len != expected_len: - raise RuntimeError( - "Backward pre hook returned an invalid number of" - f" grad_output, got {actual_len}, but expected" - f" {expected_len}" - ) - self.grad_outputs = hook_grad_outputs - - # Special case if no input required gradients, - # this hook should call the user hook directly - if self.input_tensors_index is None: - grad_inputs = self._pack_with_none([], [], self.n_inputs) - for user_hook in self.user_hooks: - res = user_hook(self.module, grad_inputs, self.grad_outputs) - if res is not None and not ( - isinstance(res, tuple) and all(el is None for el in res) - ): - raise RuntimeError( - "Backward hook for Modules where no input requires" - " gradient should always return None or None for all" - " gradients." - ) - self.grad_outputs = None - - if self.grad_outputs is not None: - assert self.output_tensors_index is not None # mypy - return tuple( - self.grad_outputs[i] for i in self.output_tensors_index - ) - - grad_fn.register_hook(hook) - - is_tuple = True - if not isinstance(args, tuple): - args = (args,) - is_tuple = False - - res, output_idx = self._apply_on_tensors(fn, args) - self.n_outputs = len(args) - self.output_tensors_index = output_idx - - if not is_tuple: - res = res[0] - return res diff --git a/ivy/functional/frontends/torchvision/ops.py b/ivy/functional/frontends/torchvision/ops.py index 1a4e7fbf49e05..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.1 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.1 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 793a3f2f02886..c5404abf5d839 100644 --- a/ivy/functional/frontends/xgboost/core.py +++ b/ivy/functional/frontends/xgboost/core.py @@ -103,11 +103,13 @@ def __init__(self, params=None, cache=None, model_file=None, compile=False): ) # add num_feature, num_target and num_instances to params - params.update({ - "num_feature": n_feat, - "num_output_group": n_output_group - 1, - "num_instances": n_inst, - }) + params.update( + { + "num_feature": n_feat, + "num_output_group": n_output_group - 1, + "num_instances": n_inst, + } + ) # create gbm(as for now only gblinear booster is available) self.gbm = GBLinear(params, compile=compile, cache=cache) @@ -121,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 ---------- @@ -154,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/gbm/gbm.py b/ivy/functional/frontends/xgboost/gbm/gbm.py index 8241acf4d29e1..41271ea82cc56 100644 --- a/ivy/functional/frontends/xgboost/gbm/gbm.py +++ b/ivy/functional/frontends/xgboost/gbm/gbm.py @@ -163,10 +163,12 @@ def _get_gradient(obj, pred, label, scale_pos_weight): # group weights for positive class are scaled w_scaled = ivy.where(label == 1.0, w * scale_pos_weight, w) - return ivy.hstack([ - obj.first_order_gradient(p, label) * w_scaled, - obj.second_order_gradient(p, label) * w_scaled, - ]) + return ivy.hstack( + [ + obj.first_order_gradient(p, label) * w_scaled, + obj.second_order_gradient(p, label) * w_scaled, + ] + ) def _pred(dt, w, base): 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 e2edeecb81802..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 ------- @@ -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 44c9f370b04ed..19b58e546e804 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 ---------- @@ -286,6 +284,7 @@ def __len__(self, /) -> int: ... @handle_nestable @handle_array_like_without_promotion @handle_out_argument +@to_native_arrays_and_back @outputs_to_ivy_arrays @handle_array_function @handle_device @@ -299,9 +298,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 +409,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 +494,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 +558,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 +656,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 +763,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 +882,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 +994,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 +1050,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 +1108,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 +1158,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 +1212,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 +1355,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 +1458,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 +1582,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 +1685,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,9 +1724,8 @@ 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 or PyCapsule Object. + """Return a new array containing the data from another (array) object with + a ``__dlpack__`` method or PyCapsule Object. Parameters ---------- @@ -1794,8 +1781,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 +1886,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 +1950,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 +2023,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 +2066,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 +2170,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 +2235,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 0454871cb9f2f..a7a7c6e1c1af7 100644 --- a/ivy/functional/ivy/device.py +++ b/ivy/functional/ivy/device.py @@ -59,8 +59,7 @@ def __init__( device: Union[ivy.Device, ivy.NativeDevice], /, ) -> None: - """ - Initialize the DefaultDevice class. + """Initialize the DefaultDevice class. Parameters ---------- @@ -76,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 ------- @@ -103,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 ---------- @@ -156,7 +153,7 @@ def _get_nvml_gpu_handle(device: Union[ivy.Device, ivy.NativeDevice], /) -> int: def _shift_native_arrays_on_default_device(*args, **kwargs): with ivy.ArrayMode(False): - default_device = ivy.default_device() + default_device = ivy.default_device(as_native=True) args, kwargs = ivy.nested_map( lambda x: ( ivy.to_device(x, default_device) @@ -178,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 ---------- @@ -214,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 ---------- @@ -256,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 ---------- @@ -295,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) @@ -320,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 -------- @@ -350,8 +344,7 @@ def unset_soft_device_mode() -> None: 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 ---------- @@ -389,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 ---------- @@ -413,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 ---------- @@ -458,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 ---------- @@ -478,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 ---------- @@ -522,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 ---------- @@ -582,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 ---------- @@ -644,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 ---------- @@ -687,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 ------- @@ -705,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 ---------- @@ -731,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 ------- @@ -749,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 ------- @@ -761,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() @@ -778,12 +760,11 @@ def default_device( item: Optional[Union[list, tuple, dict, ivy.Array, ivy.NativeArray]] = 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 ---------- @@ -845,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) @@ -877,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 -------- @@ -911,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 ---------- @@ -952,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 @@ -990,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 ---------- @@ -1049,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 ---------- @@ -1193,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) @@ -1225,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 ---------- @@ -1245,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( @@ -1277,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 ---------- @@ -1326,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 ---------- @@ -1340,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. """ @@ -1349,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 6a250ecb3053f..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,7 +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) @@ -140,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** @@ -250,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** @@ -335,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) { @@ -361,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** @@ -511,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** @@ -600,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** @@ -709,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** @@ -794,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** @@ -970,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 ---------- @@ -1073,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 ---------- @@ -1167,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 ---------- @@ -1206,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) { @@ -1226,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) @@ -1245,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 ---------- @@ -1296,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 ---------- @@ -1385,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 @@ -1501,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 ---------- @@ -1606,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** @@ -1697,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** @@ -1784,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** @@ -1861,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]) @@ -1904,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** @@ -2096,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 ---------- @@ -2213,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 @@ -2299,7 +2288,7 @@ def exp( -------- With :class:Number: - >>> x = 3 + >>> x = 3. >>> y = ivy.exp(x) >>> print(y) ivy.array(20.08553692) @@ -2352,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 ---------- @@ -2406,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 ---------- @@ -2450,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 ---------- @@ -2492,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 ---------- @@ -2533,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 @@ -2660,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** @@ -2751,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, @@ -2949,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 ---------- @@ -2997,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 ---------- @@ -3098,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 ---------- @@ -3185,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 ---------- @@ -3272,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. @@ -3458,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 ---------- @@ -3558,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 ---------- @@ -3681,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 ---------- @@ -3791,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 ---------- @@ -3881,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** @@ -3982,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** @@ -4077,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 @@ -4196,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** @@ -4258,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')]), @@ -4294,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** @@ -4395,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 ---------- @@ -4439,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 ---------- @@ -4540,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 @@ -4638,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 @@ -4730,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 ---------- @@ -4832,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 ---------- @@ -4891,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 @@ -4978,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** @@ -5161,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 ---------- @@ -5238,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** @@ -5384,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 ---------- @@ -5457,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 @@ -5587,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 @@ -5709,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 @@ -5818,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. @@ -5913,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} @@ -6000,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.]) @@ -6037,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 @@ -6151,7 +6110,7 @@ def sqrt( b: ivy.array([[7., 1.], [0., 4.47]]) } - """ + """ # noqa: E501 return ivy.current_backend(x).sqrt(x, out=out) @@ -6169,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 ---------- @@ -6244,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 ---------- @@ -6414,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** @@ -6557,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.. @@ -6615,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** @@ -6708,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 ---------- @@ -6772,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 ---------- @@ -6806,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]) @@ -6864,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 ---------- @@ -6897,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]) @@ -6955,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 ---------- @@ -6994,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 ---------- @@ -7014,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]) @@ -7040,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) { @@ -7048,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) @@ -7073,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 ---------- @@ -7151,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 ---------- @@ -7212,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 ---------- @@ -7278,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 ---------- @@ -7322,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 fe15ccc31721f..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 ---------- @@ -738,8 +726,7 @@ def threshold( value: float, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Apply the threshold function element-wise. + """Apply the threshold function element-wise. Parameters ---------- @@ -798,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 ---------- @@ -861,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) @@ -940,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 ---------- @@ -968,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) @@ -976,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 bbda425e2ccbe..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 ---------- @@ -988,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 ---------- @@ -1098,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) @@ -1149,9 +1134,8 @@ def unsorted_segment_mean( 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. + """Compute the mean of elements along segments of an array. Segments are + defined by an integer array of segment IDs. Parameters ---------- @@ -1184,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 ---------- @@ -1197,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 b88ac84f01efd..d70889c3745c9 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 ---------- @@ -306,8 +303,7 @@ def avg_pool1d( 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 ---------- @@ -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 ---------- @@ -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 ---------- @@ -1491,7 +1475,7 @@ def nearest_interpolate(x, dims, size, scale, exact): for d in range(dims): n = size[d] offsets = (ivy.arange(n, dtype="float32") + off) * scale[d] - offsets = ivy.astype(ivy.floor(ivy.astype(offsets, "float32")), "int32") + offsets = ivy.astype(ivy.floor(ivy.astype(offsets, "float32")), "int64") x = ivy.gather(x, offsets, axis=d + 2) return x @@ -1707,11 +1691,20 @@ def area_interpolate(x, dims, size, scale): def get_interpolate_kernel(mode): kernel_func = _triangle_kernel if mode == "tf_bicubic": - kernel_func = lambda inputs: _cubic_kernel(inputs) + + 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 @@ -1767,9 +1760,8 @@ def interpolate( 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 ---------- @@ -1918,14 +1910,18 @@ def interpolate( 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) - ]) - kernel_h = ivy.array([ - _mitchellcubic_kernel((p_i - i) * scale_h) - for j in range(top, bottom) - ]) + kernel_w = ivy.array( + [ + _mitchellcubic_kernel((p_j - j) * scale_w) + for i in range(left, right) + ] + ) + kernel_h = ivy.array( + [ + _mitchellcubic_kernel((p_i - i) * scale_h) + for j in range(top, bottom) + ] + ) left_pad = max(0, -left) right_pad = max(0, right - in_width) top_pad = max(0, -top) @@ -2109,9 +2105,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 ---------- @@ -2196,15 +2191,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 ---------- @@ -2284,19 +2378,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 ------- @@ -2312,6 +2408,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) @@ -2321,6 +2423,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 @@ -2333,10 +2440,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 @@ -2351,6 +2463,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 @@ -2499,8 +2616,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 ---------- @@ -2632,8 +2748,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 ---------- @@ -2709,8 +2824,7 @@ def fft2( 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 ---------- @@ -2786,8 +2900,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 ---------- @@ -2871,8 +2984,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 @@ -2940,7 +3053,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) @@ -2980,8 +3094,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 ---------- @@ -3025,7 +3138,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]) @@ -3072,8 +3185,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. @@ -3166,8 +3278,8 @@ def max_unpool1d( 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 ---------- @@ -3238,3 +3350,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 4aea8a58c4c3b..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 ---------- @@ -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,22 +1722,22 @@ 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)) fixed_factors = sorted(fixed_factors) - modes_fixed, factors_fixed = zip(*[ - (i, f) for (i, f) in enumerate(factors) if i in fixed_factors - ]) + modes_fixed, factors_fixed = zip( + *[(i, f) for (i, f) in enumerate(factors) if i in fixed_factors] + ) core = multi_mode_dot(core, factors_fixed, modes=modes_fixed) - modes, factors = zip(*[ - (i, f) for (i, f) in enumerate(factors) if i not in fixed_factors - ]) + modes, factors = zip( + *[(i, f) for (i, f) in enumerate(factors) if i not in fixed_factors] + ) init = (core, list(factors)) rank = ivy.TuckerTensor.validate_tucker_rank(x.shape, rank=rank) @@ -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 3f3fd22d9c0cf..d61a7106db12c 100644 --- a/ivy/functional/ivy/experimental/manipulation.py +++ b/ivy/functional/ivy/experimental/manipulation.py @@ -98,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 ---------- @@ -260,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 ---------- @@ -310,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 ---------- @@ -359,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 ---------- @@ -403,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 ---------- @@ -448,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 ---------- @@ -495,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 ---------- @@ -583,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 ---------- @@ -662,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 ---------- @@ -708,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 ---------- @@ -1053,8 +1046,7 @@ def pad( reflect_type: Literal["even", "odd"] = "even", **kwargs: Optional[Any], ) -> ivy.Array: - """ - Pad an array. + """Pad an array. Parameters ---------- @@ -1293,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 ---------- @@ -1344,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 ---------- @@ -1395,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 ---------- @@ -1440,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 ---------- @@ -1481,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 ---------- @@ -1527,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 ---------- @@ -1588,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 ---------- @@ -1639,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 ---------- @@ -1686,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 ---------- @@ -1728,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 ---------- @@ -1770,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 ---------- @@ -1812,11 +1797,12 @@ 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, values = ivy.promote_types_of_inputs(arr, values) arr_shape = arr.shape # array containing all flat indices @@ -1865,8 +1851,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 ---------- @@ -1947,8 +1932,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 ---------- @@ -2054,8 +2038,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 ---------- @@ -2140,9 +2123,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 ---------- @@ -2188,8 +2170,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 ---------- @@ -2251,12 +2232,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 ---------- @@ -2289,9 +2269,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 ---------- @@ -2324,18 +2304,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 ---------- @@ -2384,12 +2364,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 ---------- @@ -2426,14 +2405,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 ---------- @@ -2472,12 +2450,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 ---------- @@ -2512,8 +2489,7 @@ def matricize( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Matricizes the given tensor. + """Matricizes the given tensor. Parameters ---------- @@ -2570,8 +2546,7 @@ def soft_thresholding( *, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Soft-thresholding operator. + """Soft-thresholding operator. sign(tensor) * max[abs(tensor) - threshold, 0] @@ -2631,8 +2606,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 ---------- @@ -2654,17 +2628,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 @@ -2678,8 +2652,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 @@ -2751,8 +2724,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,...]; @@ -2857,12 +2829,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 ---------- @@ -2900,3 +2871,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 ddc8a1520cbb6..5418c3fb50df8 100644 --- a/ivy/functional/ivy/experimental/norms.py +++ b/ivy/functional/ivy/experimental/norms.py @@ -120,11 +120,11 @@ def local_response_norm( 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. + """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 ---------- @@ -453,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 ---------- @@ -489,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/sparse_array.py b/ivy/functional/ivy/experimental/sparse_array.py index 623a38a918afa..4a82fb4f97ad9 100644 --- a/ivy/functional/ivy/experimental/sparse_array.py +++ b/ivy/functional/ivy/experimental/sparse_array.py @@ -766,10 +766,12 @@ def _bsr_to_dense_coordinates(self): for col in cols: for col_index in range(nblockcols): for row_index in range(nblockrows): - all_coordinates.append([ - nblockrows * row + row_index, - nblockcols * col + col_index, - ]) + all_coordinates.append( + [ + nblockrows * row + row_index, + nblockcols * col + col_index, + ] + ) return all_coordinates def _bsc_to_dense_coordinates(self): @@ -785,10 +787,12 @@ def _bsc_to_dense_coordinates(self): for row in rows: for col_index in range(nblockcols): for row_index in range(nblockrows): - all_coordinates.append([ - nblockrows * row + row_index, - nblockcols * col + col_index, - ]) + all_coordinates.append( + [ + nblockrows * row + row_index, + nblockcols * col + col_index, + ] + ) return all_coordinates def to_dense_array(self, *, native=False): 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 f0e7ad7af4f76..d312ecdb72daf 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 -------- @@ -187,8 +188,7 @@ def get_referrers_recursive( 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 ---------- @@ -1023,31 +1004,32 @@ def clip_vector_norm( >>> x = ivy.array([0., 1., 2.]) >>> y = ivy.clip_vector_norm(x, 2.0) >>> print(y) - ivy.array([0. , 0.894, 1.79 ]) + ivy.array([0. , 0.89442718, 1.78885436]) >>> x = ivy.array([0.5, -0.7, 2.4]) >>> y = ivy.clip_vector_norm(x, 3.0, p=1.0) >>> print(y) - ivy.array([ 0.417, -0.583, 2. ]) + ivy.array([ 0.41666666, -0.58333331, 2. ]) >>> x = ivy.array([[[0., 0.], [1., 3.], [2., 6.]], ... [[3., 9.], [4., 12.], [5., 15.]]]) >>> y = ivy.zeros(((2, 3, 2))) >>> ivy.clip_vector_norm(x, 4.0, p=1.0, out=y) >>> print(y) - ivy.array([[[0. , 0. ], - [0.0667, 0.2 ], - [0.133 , 0.4 ]], - [[0.2 , 0.6 ], - [0.267 , 0.8 ], - [0.333 , 1. ]]]) + ivy.array([[[0. , 0. ], + [0.06666667, 0.20000002], + [0.13333334, 0.40000004]], + + [[0.20000002, 0.60000002], + [0.26666668, 0.80000007], + [0.33333334, 1. ]]])) >>> x = ivy.array([[1.1, 2.2, 3.3], ... [-4.4, -5.5, -6.6]]) >>> ivy.clip_vector_norm(x, 1.0, p=3.0, out=x) >>> print(x) - ivy.array([[ 0.131, 0.263, 0.394], - [-0.526, -0.657, -0.788]]) + ivy.array([[ 0.13137734, 0.26275468, 0.39413199], + [-0.52550936, -0.6568867 , -0.78826398]]) With :class:`ivy.Container` input: @@ -1056,8 +1038,8 @@ def clip_vector_norm( >>> y = ivy.clip_vector_norm(x, 2.0) >>> print(y) { - a: ivy.array([0., 0.894, 1.79]), - b: ivy.array([0.849, 1.13, 1.41]) + a: ivy.array([0., 0.89442718, 1.78885436]), + b: ivy.array([0.84852815, 1.1313709, 1.41421366]) } With multiple :class:`ivy.Container` inputs: @@ -1068,8 +1050,8 @@ def clip_vector_norm( >>> y = ivy.clip_vector_norm(x, max_norm) >>> print(y) { - a: ivy.array([0., 0.894, 1.79]), - b: ivy.array([2.449, 2.65, 2.83]) + a: ivy.array([0., 0.89442718, 1.78885436]), + b: ivy.array([1.27279221, 1.69705628, 2.12132034]) } """ norm = ivy.vector_norm(x, keepdims=True, ord=p) @@ -1095,8 +1077,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 +1160,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 +1260,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 ---------- @@ -1339,9 +1318,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 +1378,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 +1459,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 +1550,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 +1569,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 +1613,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 +1657,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 +1687,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 +1733,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 +1786,7 @@ def cached_fn(*args, **kwargs): @handle_exceptions def current_backend_str() -> Union[str, None]: - """ - Return framework string. + """Return framework string. Returns ------- @@ -1843,8 +1812,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 +1947,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 +2023,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 +2083,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 +2110,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 +2137,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 +2152,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 +2177,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 +2210,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 ---------- @@ -2343,9 +2309,8 @@ def stable_pow( *, 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 +2398,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 +2433,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 +2456,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 +2472,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 +2503,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 +2528,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 +2545,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 +2557,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 +2579,7 @@ def unset_tmp_dir() -> None: @handle_exceptions def container_types(): - """ - Summary. + """Summary. Returns ------- @@ -2636,8 +2596,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 +2609,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 +2625,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 +2691,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 +2763,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 +2798,24 @@ 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) + x_shape = ( + x.shape if ivy.current_backend_str() == "" else ivy.shape(x, as_array=True) + ) + 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 +2841,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,16 +2869,27 @@ 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) ivy.array([[ 0, -1, 20], [10, 10, 10]]) """ + # TODO: we may be able to remove this logic by instead tracing _parse_query as a node in the graph?? + if isinstance(query, (list, tuple)) and any( + [q is Ellipsis or (isinstance(q, slice) and q.stop is None) for q in query] + ): + # use numpy for item setting when an ellipsis or unbounded slice is present, + # as they would otherwise cause static dim sizes to be traced into the graph + # NOTE: this does however cause tf.function to be incompatible + np_array = x.numpy() + np_array[query] = np.asarray(val) + return ivy.array(np_array) + if copy: x = ivy.copy_array(x) if not ivy.is_array(val): @@ -2922,13 +2899,14 @@ def set_item( if ivy.is_array(query) and ivy.is_bool_dtype(query): if not len(query.shape): query = ivy.tile(query, (x.shape[0],)) - 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, ivy.shape(x, as_array=True), scatter=True + ) if indices is None: return x - val = _broadcast_to(val, target_shape).astype(x.dtype) + val = val.astype(x.dtype) ret = ivy.scatter_nd(indices, val, reduction="replace", out=x) return ret @@ -2943,27 +2921,250 @@ 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(ivy.shape(array_queries[0], as_array=True))] + + [[] for _ in range(len(array_inds) - 1)] + + [ + list(ivy.shape(query[i], as_array=True)) + 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 - # convert the flat indices to multi-D indices - x_idxs = ivy.unravel_index(x_idxs, x_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 - # 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) - return x_idxs, target_shape +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 list(_flatten_gen(iterable)) def _numel(shape): @@ -2976,16 +3177,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 +3194,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 +3290,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 +3337,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 +3367,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 +3438,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 +3502,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 +3591,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 +3697,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 ---------- @@ -3624,8 +3807,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 ---------- @@ -3692,8 +3874,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 ---------- @@ -3752,8 +3933,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 ---------- @@ -3787,8 +3967,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 --------- @@ -3813,8 +3992,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 -------- @@ -3842,8 +4020,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 ---------- @@ -3889,11 +4066,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 ---------- @@ -4033,7 +4254,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) @@ -4046,9 +4267,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() @@ -4062,7 +4283,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: @@ -4080,7 +4301,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: @@ -4105,11 +4326,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 ---------- @@ -4154,11 +4374,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 ---------- @@ -4204,8 +4423,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 ---------- @@ -4250,7 +4468,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 @@ -4270,8 +4488,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 ---------- @@ -4318,8 +4535,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 ---------- @@ -4351,8 +4567,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 ---------- @@ -4383,8 +4598,7 @@ 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 ---------- diff --git a/ivy/functional/ivy/gradients.py b/ivy/functional/ivy/gradients.py index 6740e800462a4..690899f46f27c 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] `_ @@ -768,7 +763,7 @@ def adam_step( b: ivy.array([0.216, 0.384, 0.6]) }) """ - step = float(step) + step = ivy.to_scalar(step) mw = ivy.add(beta1 * mw, (1 - beta1) * dcdw) dcdw_sqrd = dcdw**2 vw = ivy.add(ivy.multiply(beta2, vw), (1 - beta2) * dcdw_sqrd) @@ -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 43a18e56a73d7..508a090f10e3f 100644 --- a/ivy/functional/ivy/layers.py +++ b/ivy/functional/ivy/layers.py @@ -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. @@ -200,7 +199,7 @@ def linear( num_outer_batch_dims = len(outer_batch_shape) inner_batch_shape = list(x.shape[num_outer_batch_dims:-1]) num_inner_batch_dims = len(inner_batch_shape) - num_out_feats, num_in_feats = list(weight.shape[-2:]) + num_out_feats, num_in_feats = weight.shape[-2], weight.shape[-1] # OBS x IBS x OF y = ivy.matmul( @@ -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 @@ -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 ---------- @@ -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 # @@ -2510,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 ---------- @@ -2604,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 54f8f94378641..4c61f9fdbbaa0 100644 --- a/ivy/functional/ivy/linear_algebra.py +++ b/ivy/functional/ivy/linear_algebra.py @@ -13,6 +13,7 @@ handle_array_like_without_promotion, handle_device, handle_backend_invalid, + infer_dtype, ) from ivy.utils.exceptions import handle_exceptions @@ -39,8 +40,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 +183,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 +282,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 +362,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 +539,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 +592,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 +704,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 +812,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 +890,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 +987,7 @@ def matmul( adjoint_b: bool = False, out: Optional[ivy.Array] = None, ) -> ivy.Array: - """ - Compute the matrix product. + """Compute the matrix product. Parameters ---------- @@ -1143,6 +1137,7 @@ def matmul( @handle_out_argument @to_native_arrays_and_back @handle_array_function +@infer_dtype @handle_device def matrix_norm( x: Union[ivy.Array, ivy.NativeArray], @@ -1151,10 +1146,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 +1201,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 +1292,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 +1307,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 +1414,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 +1527,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 +1616,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 +1667,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 +1698,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 +1773,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 +1951,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 +1961,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 +1995,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 +2037,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 +2048,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 +2067,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 +2081,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 +2108,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 +2240,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 ---------- @@ -2332,7 +2301,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], @@ -2413,8 +2382,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 @@ -2466,7 +2434,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.]]) @@ -2514,9 +2482,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** @@ -2649,7 +2616,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), @@ -2699,8 +2666,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 ---------- @@ -2798,8 +2764,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 ---------- @@ -2901,13 +2866,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]) @@ -2944,9 +2909,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 ---------- @@ -3029,11 +2993,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 ---------- @@ -3123,41 +3087,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 @@ -3182,7 +3111,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..1e8d6cebb511e 100644 --- a/ivy/functional/ivy/losses.py +++ b/ivy/functional/ivy/losses.py @@ -39,13 +39,12 @@ def cross_entropy( pred: Union[ivy.Array, ivy.NativeArray], /, *, - axis: int = -1, + axis: Optional[int] = None, epsilon: float = 1e-7, 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 318c663b739b7..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 ---------- @@ -1094,8 +1085,7 @@ def repeat( 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 7ba70923ae8e6..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. @@ -89,10 +88,12 @@ def cost_fn_with_variable(v): else variables.cont_prune_key_chains(outer_v, ignore_none=True) ) - inner_grads = ivy.Container({ - k: ivy.zeros_like(v) if k not in inner_grads else inner_grads[k] - for k, v in var.cont_to_iterator() - }) + inner_grads = ivy.Container( + { + k: ivy.zeros_like(v) if k not in inner_grads else inner_grads[k] + for k, v in var.cont_to_iterator() + } + ) if batched: inner_grads = ivy.multiply(inner_grads, num_tasks) @@ -152,14 +153,16 @@ def _train_task( if keep_innver_v else variables.cont_prune_key_chains(inner_v, ignore_none=True) ) - inner_update_grads = ivy.Container({ - k: ( - ivy.zeros_like(v) - if k not in inner_update_grads - else inner_update_grads[k] - ) - for k, v in var.cont_to_iterator() - }) + inner_update_grads = ivy.Container( + { + k: ( + ivy.zeros_like(v) + if k not in inner_update_grads + else inner_update_grads[k] + ) + for k, v in var.cont_to_iterator() + } + ) if batched: inner_update_grads = ivy.multiply(inner_update_grads, num_tasks) @@ -259,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: @@ -474,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 ---------- @@ -590,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 ---------- @@ -740,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 9ed54e924b8f1..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,7 +239,7 @@ 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]] """ @@ -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 ---------- @@ -1356,14 +1341,16 @@ def copy_nest( return class_instance(**dict(zip(nest._fields, ret_list))) return class_instance(tuple(ret_list)) elif check_fn(nest, list): - return class_instance([ - copy_nest( - i, - include_derived=include_derived, - to_mutable=to_mutable, - ) - for i in nest - ]) + return class_instance( + [ + copy_nest( + i, + include_derived=include_derived, + to_mutable=to_mutable, + ) + for i in nest + ] + ) elif check_fn(nest, dict): class_instance = type(nest) dict_ = { @@ -1391,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 ---------- @@ -1479,9 +1465,9 @@ def nested_multi_map( ( return_nest.append(ret) if isinstance(return_nest, (list)) - else return_nest.update({ - val if is_dict else list(nest)[index]: ret - }) + else return_nest.update( + {val if is_dict else list(nest)[index]: ret} + ) ) else: values = nests @@ -1523,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: @@ -1541,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 ---------- @@ -1572,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..517f5ad361b2a 100644 --- a/ivy/functional/ivy/statistical.py +++ b/ivy/functional/ivy/statistical.py @@ -12,6 +12,7 @@ handle_array_like_without_promotion, handle_device, handle_backend_invalid, + infer_dtype, ) from ivy.utils.exceptions import handle_exceptions @@ -48,10 +49,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 +85,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 +147,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 +168,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 @@ -261,17 +269,18 @@ def max( @handle_out_argument @to_native_arrays_and_back @handle_array_function +@infer_dtype @handle_device def mean( x: Union[ivy.Array, ivy.NativeArray], /, - *, axis: Optional[Union[int, Sequence[int]]] = None, keepdims: bool = False, + *, + dtype: Optional[Union[ivy.Dtype, ivy.NativeDtype]] = None, 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** @@ -293,6 +302,10 @@ def mean( 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``. + dtype + the desired data type of returned tensor. If specified, the input tensor + is casted to dtype before the operation is performed. This is useful for + preventing data type overflows. Default: None. out optional output array, for writing the result to. @@ -363,7 +376,9 @@ def mean( b: ivy.array([4.5, 5.5, 6.5]) } """ - return current_backend(x).mean(x, axis=axis, keepdims=keepdims, out=out) + return current_backend(x).mean( + x, axis=axis, keepdims=keepdims, dtype=dtype, out=out + ) @handle_exceptions @@ -383,8 +398,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 +533,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 +671,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 +811,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 +927,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 +1072,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 +1108,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 +1126,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 +1149,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 +1162,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 +1171,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 +1192,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 635aa7dc30161..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): @@ -522,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 ---------- @@ -551,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 0636de01aa7b5..541829bc3d18b 100644 --- a/ivy/stateful/converters.py +++ b/ivy/stateful/converters.py @@ -21,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 ---------- @@ -76,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 ---------- @@ -170,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 ---------- @@ -260,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 ---------- @@ -323,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 ---------- @@ -380,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 ---------- @@ -440,8 +434,8 @@ def from_torch_module( ) def to_keras_module(self): - """ - Convert a `ivy.Module` module instance to a `tf.keras.Model` instance. + """Convert a `ivy.Module` module instance to a `tf.keras.Model` + instance. Returns ------- @@ -458,7 +452,7 @@ def to_keras_module(self): class KerasModel(tf.keras.Model): def __init__(self, ivy_module): - super(KerasModel, self).__init__() + super().__init__() self._ivy_module = ivy_module self._parameters = {} self._assign_variables() @@ -476,13 +470,19 @@ def _assign_variables(self): ), ) self._ivy_module.v.cont_map( - lambda x, kc: self.add_weight( - name=kc, shape=x.shape, dtype=x.dtype, trainable=True + 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)) + lambda x, kc: ( + model_weights.append(ivy.to_numpy(x)) if x is not None else x + ) ) self.set_weights(model_weights) @@ -498,6 +498,8 @@ def _populate_params(self): 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) @@ -505,7 +507,7 @@ def __update_param(ivy_module, x, kc): module = module.__getattribute__(key) if hasattr(module, "_update_v"): module._update_v({keys[-1]: self._parameters[kc]}) - return 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), @@ -525,11 +527,13 @@ def call(self, *args, training=None, **kwargs): return ret def __call__(self, *args, **kwargs): - ivy.set_backend("tensorflow") - args, kwargs = ivy.args_to_new_backend(*args, native=True, **kwargs) - ivy.previous_backend() - - return super(KerasModel, self).__call__(*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) diff --git a/ivy/stateful/helpers.py b/ivy/stateful/helpers.py index 7d94f5e0f229f..c62ea0bea79f1 100644 --- a/ivy/stateful/helpers.py +++ b/ivy/stateful/helpers.py @@ -1,582 +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. + None """ - 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 "" + _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 - def show_v_in_top_v(self, /, *, depth=None): - """ - Show sub containers from the perspective of the top layer. Will give prompt if - either of `v` or `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``. - """ - 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. - - 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}" - ) + 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 - 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..e83898cda358e 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,6 +2261,73 @@ def _forward(self, x): norm=self.norm, ) + def _extra_repr(self): + s = "type={type}" + if self.n is not None: + s += ", n={n}" + if self.axis != -1: + s += ", axis={axis}" + if self.norm is not None: + s += ", norm={norm}" + return s.format(**self.__dict__) + + +class IDct(Module): + def __init__( + self, + *, + type=2, + n=None, + axis=-1, + norm=None, + device=None, + dtype=None, + ): + """Class for applying the Discrete Cosine Transform over mini-batch of + inputs. + + Parameters + ---------- + x + The input signal. + type + The type of the idct. Must be 1, 2, 3 or 4. + n + The length of the transform. If n is less than the input signal length, + then x is truncated, if n is larger then x is zero-padded. + axis + The axis to compute the IDCT along. + norm + The type of normalization to be applied. Must be either None or "ortho". + device + device on which to create the layer's variables 'cuda:0', 'cuda:1', 'cpu' + """ + self.type = type + self.n = n + self.axis = axis + self.norm = norm + Module.__init__(self, device=device, dtype=dtype) + + def _forward(self, x): + """Forward pass of the layer. + + Parameters + ---------- + x + The input array to the layer. + + Returns + ------- + The output array of the layer. + """ + return ivy.idct( + x, + type=self.type, + n=self.n, + axis=self.axis, + norm=self.norm, + ) + def extra_repr(self): s = "type={type}" if self.n is not None: @@ -2302,10 +2357,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 +2389,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 +2401,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 +2420,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 +2436,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 +2447,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 +2456,7 @@ def __init__(self): Module.__init__(self) def _forward(self, x): - """ - Forward pass of the layer. + """Forward pass of the layer. Parameters ---------- @@ -2433,8 +2485,7 @@ def __init__( device=None, dtype=None, ): - """ - Class for applying IFFT to input. + """Class for applying IFFT to input. Parameters ---------- @@ -2460,8 +2511,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 +2529,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 6758859cef555..7c1c83ed6c96d 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 + self.build(*args, dynamic_backend=dynamic_backend, **kwargs) - 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. - - 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,95 +286,105 @@ 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 + + # 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 + ) + + self._lazy_traced = False + + def register_buffer(self, name, value): + """Register a buffer. + + Parameters + ---------- + name + Name of the buffer + value + Value of the buffer + """ + if value is not None: + self._buffers.update({name: value}) + else: + super().__setattr__(name, value) + + def register_parameter(self, name, value): + """Register a parameter. + + Parameters + ---------- + name + Name of the parameter + value + Value of the parameter + """ + self._v.update({name: value}) def train(self, mode: bool = True): - # enables/disables training mode - self.training = mode + """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 + + def eval(self): + """Disable training mode.""" + return self.train(mode=False) def to_device(self, device): - # moves the weights and buffers - # to the specified device + """Move 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(): + 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 __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 - - 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" - - main_str += ")" - return main_str - - def extra_repr(self) -> str: - r""" - 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 "" - - def _get_name(self): - return self.__class__.__name__ - - # Properties # - # -----------# - - @property - def build_mode(self): - return self._build_mode - - @property - def built_(self): - return self._built - - @property - def device(self): - return self._device - def show_graph( self, randomness_factor: float = 0.1, @@ -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): @@ -1061,8 +679,7 @@ def _create_variables(self, device, dtype): return self._hk_params def _build(self, params_hk, *args, **kwargs): - pass - + ivy.set_jax_backend() args, kwargs = ivy.args_to_native(*args, **kwargs) # noinspection PyUnresolvedReferences params_dict = self._hk_flat_map_to_dict(params_hk) @@ -1073,12 +690,13 @@ def _build(self, params_hk, *args, **kwargs): self._device = ivy.as_ivy_dev(param0.device()) else: self._device = ivy.as_ivy_dev("cpu") + ivy.previous_backend() 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) @@ -1159,7 +777,10 @@ def _create_variables(self, device=None, dtype=None): def _build(self, *args, **kwargs): self._native_params = ivy.Container( OrderedDict( - sorted([(param.name, param) for param in self._native_module.variables]) + sorted( + [(param.name, param) for param in self._native_module.variables], + key=lambda kv: kv[0], + ) ), dynamic_backend=False, ) @@ -1167,7 +788,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) @@ -1185,10 +806,12 @@ def _create_variables(self, device=None, dtype=None): def _build(self, *args, **kwargs): self._native_params = ivy.Container( OrderedDict( - sorted([ - (k.replace(".", "/"), v) - for k, v in dict(self._native_module.named_parameters()).items() - ]) + sorted( + [ + (k.replace(".", "/"), v) + for k, v in dict(self._native_module.named_parameters()).items() + ] + ) ), dynamic_backend=False, ) @@ -1196,7 +819,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) @@ -1216,10 +839,12 @@ def _create_variables(self, device=None, dtype=None): def _build(self, *args, **kwargs): self._native_params = ivy.Container( OrderedDict( - sorted([ - (k.replace(".", "/"), v) - for k, v in dict(self._native_module.named_parameters()).items() - ]) + sorted( + [ + (k.replace(".", "/"), v) + for k, v in dict(self._native_module.named_parameters()).items() + ] + ) ), dynamic_backend=False, ) @@ -1261,5 +886,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..d10cfc5d7e5ca 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 3ce9cb927f8be..185a745400445 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( @@ -184,7 +205,7 @@ def check_same_dtype(x1, x2, message=""): 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_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 @@ -327,6 +348,7 @@ def _check_jax_x64_flag(dtype): ivy.backend == "jax" and not ivy.functional.backends.jax.jax.config.jax_enable_x64 ): + 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 2012d8ed9ec03..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 @@ -328,8 +326,7 @@ def _map_fn(x): @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 @@ -361,7 +358,6 @@ def set_backend(backend: str, dynamic: bool = False): global ivy_original_dict if not backend_stack: ivy_original_dict = ivy.__dict__.copy() - _clear_current_sub_backends() if isinstance(backend, str): temp_stack = [] @@ -379,7 +375,7 @@ 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] @@ -394,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 @@ -403,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 @@ -412,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")`. """ @@ -421,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 @@ -430,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 @@ -439,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 @@ -449,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,9 +524,9 @@ def choose_random_backend(excluded=None): or not installed.""", as_array=False, ) - f = np.random.choice([ - f_srt for f_srt in list(_backend_dict.keys()) if f_srt not in excluded - ]) + f = np.random.choice( + [f_srt for f_srt in list(_backend_dict.keys()) if f_srt not in excluded] + ) if f is None: excluded.append(f) continue @@ -568,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/binaries.py b/ivy/utils/binaries.py index 34948140db9c8..02975eb7c0084 100644 --- a/ivy/utils/binaries.py +++ b/ivy/utils/binaries.py @@ -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)) @@ -33,17 +34,20 @@ def check_for_binaries(): for path in binaries_paths: if not os.path.exists(path): if initial: - config_str = "\n".join([ - f"{module} : {', '.join(configs)}" - for module, configs in available_configs.items() - ]) + config_str = "\n".join( + [ + f"{module} : {', '.join(configs)}" + for module, configs in available_configs.items() + ] + ) logging.warning( "\tSome binaries seem to be missing in your system. This could " "be either because we don't have compatible binaries for your " "system or that newer binaries were available. In the latter " "case, calling ivy.utils.cleanup_and_fetch_binaries() should " "fetch the binaries binaries. Feel free to create an issue on " - "https://github.com/unifyai/ivy.git in case of the former\n" + "https://github.com/ivy-llc/ivy.git in " + "case of the former\n" ) logging.warning( "\nFollowing are the supported configurations" @@ -76,6 +80,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 @@ -93,11 +98,12 @@ 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( - "https://github.com/unifyai/binaries/raw/" + "https://github.com/ivy-llc/binaries/raw/" f"{version}/{search_path}", timeout=40, ) diff --git a/ivy/utils/decorator_utils.py b/ivy/utils/decorator_utils.py new file mode 100644 index 0000000000000..b2c392062d553 --- /dev/null +++ b/ivy/utils/decorator_utils.py @@ -0,0 +1,408 @@ +import functools +import re +import inspect +from enum import Enum +import ast +import copy +import os +import ivy + +DATA_FORMAT = "PT" +CONV_FUNCS = [ + "Conv1d", + "Conv2d", + "Conv3d", + "ConvTranspose1d", + "ConvTranspose2d", + "ConvTranspose3d", +] +KERAS_CONV_FUNCS = [ + "KerasConv1D", + "KerasConv2D", + "KerasConv3D", + "KerasDepthwiseConv2D", + "KerasConv1DTranspose", + "KerasConv2DTranspose", + "KerasConv3DTranspose", +] +POOL_FUNCS = [ + "MaxPool1d", + "MaxPool2d", + "MaxPool3d", + "AvgPool1d", + "AvgPool2d", + "AvgPool3d", + "FractionalMaxPool2d", + "LPPool1d", + "LPPool2d", + "AdaptiveMaxPool1d", + "AdaptiveMaxPool2d", + "AdaptiveMaxPool3d", + "AdaptiveAvgPool1d", + "AdaptiveAvgPool2d", + "AdaptiveAvgPool3d", +] +KERAS_POOL_FUNCS = [ + "KerasAveragePooling1D", + "KerasAveragePooling2D", + "KerasAveragePooling3D", + "KerasMaxPool1D", + "KerasMaxPool2D", + "KerasMaxPool3D", +] +PADDING_FUNCS = [ + "ReflectionPad1d", + "ReflectionPad2d", + "ReplicationPad1d", + "ReplicationPad2d", + "ReplicationPad3d", + "ZeroPad2d", + "ConstantPad1d", + "ConstantPad2d", + "ConstantPad3d", +] +KERAS_PADDING_FUNCS = [ + "KerasZeroPadding1D", + "KerasZeroPadding2D", + "KerasZeroPadding3D", +] +ACTIVATION_FUNCS = [ + "ELU", + "Hardshrink", + "Hardsigmoid", + "Hardswish", + "Hardtanh", + "LeakyReLU", + "PReLU", + "ReLU", + "ReLU6", + "RReLU", + "SELU", + "CELU", + "GELU", + "Sigmoid", + "Softplus", + "Softshrink", + "Softsign", + "Tanh", + "Tanhshrink", + "Threshold", + "Softmin", + "Softmax", + "Softmax2d", + "LogSoftmax", + "AdaptiveLogSoftmaxWithLoss", +] +KERAS_ACTIVATION_FUNCS = [ + "KerasReLU", + "KerasPReLU", + "KerasLeakyReLU", + "KerasThresholdedReLU", + "KerasELU", + "KerasSoftmax", +] +NORM_FUNCS = [ + "_BatchNorm", + "_InstanceNorm", + "BatchNorm1d", + "BatchNorm2d", + "BatchNorm3d", + "GroupNorm", + "SyncBatchNorm", + "InstanceNorm1d", + "InstanceNorm2d", + "InstanceNorm3d", + "LocalResponseNorm", +] +KERAS_NORM_FUNCS = [ + "KerasBatchNorm1D", + "KerasBatchNorm2D", + "KerasBatchNorm3D", + "KerasLayerNormalization", + "KerasGroupNormalization", + "KerasUnitNorm1D", + "KerasUnitNorm2D", + "KerasUnitNorm3D", +] +DROPOUT_FUNCS = [ + "Dropout", + "Dropout2d", + "Dropout3d", + "AlphaDropout", + "FeatureAlphaDropout", +] +KERAS_DROPOUT_FUNCS = [ + "KerasDropout", +] + +CONV_BLOCK_FNS = [ + *CONV_FUNCS, + *KERAS_CONV_FUNCS, + *POOL_FUNCS, + *KERAS_POOL_FUNCS, + *PADDING_FUNCS, + *KERAS_PADDING_FUNCS, + *ACTIVATION_FUNCS, + *KERAS_ACTIVATION_FUNCS, + *NORM_FUNCS, + *KERAS_NORM_FUNCS, + *DROPOUT_FUNCS, + *KERAS_DROPOUT_FUNCS, +] + + +def handle_methods(fn): + def extract_function_name(s): + match = re.search(r"_(.+?)(?:_\d+)?$", s) + if match: + return match.group(1) + + @functools.wraps(fn) + def wrapper(*args, **kwargs): + if ivy.is_array(args[0]): + return fn(*args, **kwargs) + else: + fn_name = extract_function_name(fn.__name__) + new_fn = getattr(args[0], fn_name) + return new_fn(*args[1:], **kwargs) + + return wrapper + + +def handle_get_item(fn): + @functools.wraps(fn) + def wrapper(inp, query, **kwargs): + try: + res = inp.__getitem__(query) + except IndexError: + raise + except Exception: + res = fn(inp, query, **kwargs) + return res + + return wrapper + + +def handle_set_item(fn): + @functools.wraps(fn) + def wrapper(inp, query, val, **kwargs): + try: + inp.__setitem__(query, val) + res = inp + except IndexError: + raise + except Exception: + res = fn(inp, query, val, **kwargs) + return res + + return wrapper + + +def store_config_info(fn): + @functools.wraps(fn) + def wrapper(self, *args, **kwargs): + fn(self, *args, **kwargs) + # store trackable layer info + if all( + [ + hasattr(self, "_args"), + hasattr(self, "_kwargs"), + hasattr(self, "_self_tracked_trackables"), + ] + ): + orig_trackables = copy.copy(self._self_tracked_trackables) + self._args = (self,) + args + self._kwargs = kwargs + self._self_tracked_trackables = orig_trackables + + return wrapper + + +def retrieve_object(frame, name): + if name is None: + return name + + names = name.split(".") + obj = frame.f_locals.get(names[0]) or frame.f_globals.get(names[0]) + if obj is None: + return None + + for attr in names[1:]: + try: + obj = getattr(obj, attr) + except AttributeError: + return None + + return obj + + +class CallVisitor(ast.NodeVisitor): + def __init__(self): + self.func_name = None + + def visit_Call(self, node): + self.func_name = ast.unparse(node.func).strip() + return super().generic_visit(node) + + +def get_next_func(obj): + + # Traverse down the stack to reach the first occurrence of the function named "call" + stack = inspect.stack() + for frame_info in stack: + if frame_info == obj._previous_frame_info: + calling_frame = frame_info.frame + break + else: + return None + + # Check if the filename contains "Sequential" + if "Sequential" in frame_info.filename: + try: + # find the next call in the sequence + self_seq = calling_frame.f_locals["self"] + idx = calling_frame.f_locals["i"] + next_func = self_seq[idx + 1] + return next_func + except IndexError: + # If it fails, traverse further down the stack frame + # to find the next occurrence of "call" + for frame_info in stack[stack.index(frame_info) + 1 :]: + if frame_info == self_seq._previous_frame_info: + calling_frame = frame_info.frame + break + else: + return None + # Retrieve the source code for the immediate next statement + # following the one we are executing + lines, start_line_no = inspect.getsourcelines(calling_frame) + current_line_no = calling_frame.f_lineno + relative_line_no = current_line_no - start_line_no + # Parse the next statement to get the next call + try: + next_line = lines[relative_line_no + 1].strip() + tree = ast.parse(next_line) + visitor = CallVisitor() + visitor.visit(tree) + next_call_str = visitor.func_name + except Exception: + next_call_str = "" + + # Retrieve the original object from the calling frame + next_func = retrieve_object(calling_frame, next_call_str) + + return next_func + + +class TransposeType(Enum): + """Possible transpose types.""" + + NO_TRANSPOSE = "no_transpose" + CONV1D = "conv1d" + CONV2D = "conv2d" + CONV3D = "conv3d" + + +def apply_transpose(input, transpose, pt_to_tf=True): + if transpose is TransposeType.NO_TRANSPOSE: + return input + + if transpose is TransposeType.CONV1D: + # Conv1D input: + # PT: (num_out_channel, num_in_channel, kernel) + # -> TF: (kernel, num_in_channel, num_out_channel) + axes = (0, 2, 1) if pt_to_tf else (0, 2, 1) + elif transpose is TransposeType.CONV2D: + # Conv2D input: + # PT: (num_out_channel, num_in_channel, kernel[0], kernel[1]) + # -> TF: (kernel[0], kernel[1], num_in_channel, num_out_channel) + axes = (0, 2, 3, 1) if pt_to_tf else (0, 3, 1, 2) + elif transpose is TransposeType.CONV3D: + # Conv3D input: + # PT: (num_out_channel, num_in_channel, kernel[0], kernel[1], kernel[2]) + # -> TF: (kernel[0], kernel[1], kernel[2], num_in_channel, num_out_channel) + axes = (0, 2, 3, 4, 1) if pt_to_tf else (0, 4, 1, 2, 3) + + input = ivy.permute_dims(input, axes=axes).data + return input + + +def handle_transpose_in_input_and_output(fn): + + original_signature = inspect.signature(fn) + + @functools.wraps(fn) + def transpose_wrapper(self, *args, **kwargs): + global DATA_FORMAT + # isolates the actual `**kwargs` for the decorated function + kwargs_call = { + key: val + for key, val in kwargs.items() + if key not in dict(original_signature.parameters) + } + fn_args_and_kwargs = { + key: val for key, val in kwargs.items() if key not in kwargs_call + } + # move any arg into kwargs, if they exist + fn_args_and_kwargs.update(dict(zip(fn.__code__.co_varnames[1:], args))) + + conv_block_start = lambda f: any( + substr in f.__qualname__ + for substr in ( + CONV_FUNCS + + NORM_FUNCS + + POOL_FUNCS + + KERAS_CONV_FUNCS + + KERAS_NORM_FUNCS + + KERAS_POOL_FUNCS + ) + ) + next_call_in_seq = get_next_func(self) + name_of_next_call = ( + next_call_in_seq.__class__.__name__ + if hasattr(next_call_in_seq, "__class__") + else "" + ) + conv_block_continued = next_call_in_seq and any( + substr in name_of_next_call for substr in CONV_BLOCK_FNS + ) + + if DATA_FORMAT == "PT" and conv_block_start(self.__class__): + input = fn_args_and_kwargs["input"] + if len(input.shape) > 4: + transpose = TransposeType.CONV3D + elif len(input.shape) > 3: + transpose = TransposeType.CONV2D + elif len(input.shape) > 2: + transpose = TransposeType.CONV1D + else: + transpose = TransposeType.NO_TRANSPOSE + fn_args_and_kwargs["input"] = apply_transpose( + input, transpose=transpose, pt_to_tf=True + ) + + DATA_FORMAT = "TF" + os.environ["DATA_FORMAT"] = "channels_last" + + res = fn(self, **fn_args_and_kwargs) + + if (DATA_FORMAT == "TF" and conv_block_continued) or DATA_FORMAT == "PT": + return res + + if len(res.shape) > 4: + transpose = TransposeType.CONV3D + elif len(res.shape) > 3: + transpose = TransposeType.CONV2D + elif len(res.shape) > 2: + transpose = TransposeType.CONV1D + else: + transpose = TransposeType.NO_TRANSPOSE + res = apply_transpose(res, transpose=transpose, pt_to_tf=False) + + DATA_FORMAT = "PT" + os.environ["DATA_FORMAT"] = "channels_first" + + return res + + handle_transpose_in_input_and_output.__signature__ = original_signature + return transpose_wrapper diff --git a/ivy/utils/einsum_parser.py b/ivy/utils/einsum_parser.py index b7b20b89fc22c..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 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 872b12b14cc33..d8f35b27a5b0e 100644 --- a/ivy/utils/exceptions.py +++ b/ivy/utils/exceptions.py @@ -120,9 +120,9 @@ def _get_traces(curr_obj, area, local_dict, target_name): curr_obj[3] = rooted_src_list[i] curr_obj[1] += i break - elif builtins.any([ - name in rooted_src_list[i] for name in non_lib_objs_name_list - ]): + elif builtins.any( + [name in rooted_src_list[i] for name in non_lib_objs_name_list] + ): found = False for name in non_lib_objs_name_list: if name in rooted_src_list[i]: @@ -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/conftest.py b/ivy_tests/conftest.py index e573de819178c..27682491edebe 100644 --- a/ivy_tests/conftest.py +++ b/ivy_tests/conftest.py @@ -66,14 +66,14 @@ def pytest_addoption(parser): "-N", "--num-examples", action="store", - default=25, + default=15, type=int, help="set max examples generated by Hypothesis", ) parser.addoption( "--deadline", action="store", - default=500000, + default=100_000, type=int, help="set deadline for testing one example", ) @@ -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 @@ -149,6 +151,7 @@ def pytest_configure(config): "ivy_profile", **profile_settings, suppress_health_check=(HealthCheck(3), HealthCheck(2), HealthCheck(1)), + phases=[Phase.explicit, Phase.reuse, Phase.generate, Phase.target], print_blob=True, ) 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_integrations/conftest.py b/ivy_tests/test_integrations/conftest.py new file mode 100644 index 0000000000000..a11e0c16a8280 --- /dev/null +++ b/ivy_tests/test_integrations/conftest.py @@ -0,0 +1,45 @@ +import ivy +import pytest + +TARGET_FRAMEWORKS = ["numpy", "jax", "tensorflow"] +BACKEND_COMPILE = False +TARGET = "all" + + +@pytest.fixture(autouse=True) +def run_around_tests(): + ivy.unset_backend() + + +def pytest_addoption(parser): + parser.addoption( + "--backend-compile", + action="store_true", + help="Whether to backend compile the transpiled graph", + ) + parser.addoption( + "--target", + action="store", + default="all", + help="Target for the transpilation tests", + ) + + +def pytest_configure(config): + getopt = config.getoption + + global BACKEND_COMPILE + BACKEND_COMPILE = getopt("--backend-compile") + + global TARGET + TARGET = getopt("--target") + + +def pytest_generate_tests(metafunc): + configs = list() + if TARGET not in ["jax", "numpy", "tensorflow", "torch"]: + for target in TARGET_FRAMEWORKS: + configs.append((target, BACKEND_COMPILE)) + else: + configs.append((TARGET, BACKEND_COMPILE)) + metafunc.parametrize("target_framework,backend_compile", configs) diff --git a/ivy_tests/test_integrations/helpers.py b/ivy_tests/test_integrations/helpers.py new file mode 100644 index 0000000000000..10574e75060b5 --- /dev/null +++ b/ivy_tests/test_integrations/helpers.py @@ -0,0 +1,149 @@ +import ivy +import jax +import jax.numpy as jnp +import kornia +import numpy as np +import pytest +import tensorflow as tf +import torch + +jax.config.update("jax_enable_x64", True) + +jax_kornia = ivy.transpile(kornia, source="torch", to="jax") +np_kornia = ivy.transpile(kornia, source="torch", to="numpy") +tf_kornia = ivy.transpile(kornia, source="torch", to="tensorflow") + + +# Helpers # +# ------- # + + +def _check_allclose(x, y, tolerance=1e-3): + """Checks that all values are close. + + Any arrays must already be in numpy format, rather than native + framework. + """ + if type(x) != type(y): + assert False, f"mistmatched types: {type(x), type(y)}" + + if isinstance(x, np.ndarray): + assert np.allclose(x, y, atol=tolerance), "numpy array values are not all close" + return + + if isinstance(x, (list, set, tuple)): + all( + [ + _check_allclose(element_x, element_y, tolerance=tolerance) + for element_x, element_y in zip(x, y) + ] + ) + return + + if isinstance(x, dict): + keys_same = all([key_x == key_y for key_x, key_y in zip(x.keys(), y.keys())]) + values_same = all( + [ + _check_allclose(element_x, element_y, tolerance=tolerance) + for element_x, element_y in zip(x.values(), y.values()) + ] + ) + assert keys_same, "keys in dict differ" + assert values_same, "values in dict differ" + return + + if isinstance(x, float): + assert x - y < tolerance, f"float values differ: {x} != {y}" + return + + assert x == y, f"values differ: {x} != {y}" + + +def _native_array_to_numpy(x): + if isinstance(x, (torch.Tensor, tf.Tensor)): + return x.numpy() + if isinstance(x, jnp.ndarray): + return np.asarray(x) + return x + + +def _nest_array_to_numpy(nest, shallow=True): + return ivy.nested_map( + lambda x: _native_array_to_numpy(x), + nest, + include_derived=True, + shallow=shallow, + ) + + +def _array_to_new_backend( + x, + target, +): + """Converts a torch tensor to an array/tensor in a different framework. + + If the input is not a torch tensor, the input if returned without + modification. + """ + if isinstance(x, torch.Tensor): + if target == "torch": + return x + y = x.numpy() + if target == "jax": + y = jnp.array(y) + elif target == "tensorflow": + y = tf.convert_to_tensor(y) + return y + else: + return x + + +def _nest_torch_tensor_to_new_framework(nest, target, shallow=True): + return ivy.nested_map( + lambda x: _array_to_new_backend(x, target), + nest, + include_derived=True, + shallow=shallow, + ) + + +def _test_function( + fn: str, + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target, + backend_compile=False, + tolerance=1e-3, +): + if target == "jax": + prefix = "jax_" + elif target == "numpy": + prefix = "np_" + elif target == "tensorflow": + prefix = "tf_" + else: + pytest.skip() + transpiled_fn = eval(prefix + fn) + + try: + transpiled_fn(*trace_args, **trace_kwargs) + except Exception as e: + # don't fail the test if unable to connect to the server + if "Unable to connect to ivy server." in str(e): + pytest.skip() + else: + raise e + + orig_fn = eval(fn) + + orig_out = orig_fn(*test_args, **test_kwargs) + graph_args = _nest_torch_tensor_to_new_framework(test_args, target) + graph_kwargs = _nest_torch_tensor_to_new_framework(test_kwargs, target) + graph_out = transpiled_fn(*graph_args, **graph_kwargs) + + orig_np = _nest_array_to_numpy(orig_out) + graph_np = _nest_array_to_numpy(graph_out) + + _check_allclose(orig_np, graph_np, tolerance=tolerance) diff --git a/ivy_tests/test_integrations/test_kornia.py b/ivy_tests/test_integrations/test_kornia.py new file mode 100644 index 0000000000000..efeac71aa345c --- /dev/null +++ b/ivy_tests/test_integrations/test_kornia.py @@ -0,0 +1,1767 @@ +"""Tests transpiling a subset of the kornia functional api.""" + +from helpers import _test_function +import kornia +import torch + + +def test_rgb_to_grayscale(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 4, 4),) + trace_kwargs = {} + test_args = (torch.rand(5, 3, 4, 4),) + test_kwargs = {} + _test_function( + "kornia.color.rgb_to_grayscale", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_bgr_to_rgba(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 4, 4), + 1.0, + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 3, 4, 4), + 0.5, + ) + test_kwargs = {} + _test_function( + "kornia.color.bgr_to_rgba", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_rgb_to_hsv(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 5, 5),) + trace_kwargs = {"eps": 1e-8} + test_args = (torch.rand(5, 3, 5, 5),) + test_kwargs = {"eps": 1e-2} + _test_function( + "kornia.color.rgb_to_hsv", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_luv_to_rgb(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 5, 5),) + trace_kwargs = {"eps": 1e-12} + test_args = (torch.rand(5, 3, 5, 5),) + test_kwargs = {"eps": 1e-12} + _test_function( + "kornia.color.luv_to_rgb", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_ycbcr_to_rgb(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 5, 5),) + trace_kwargs = {} + test_args = (torch.rand(5, 3, 5, 5),) + test_kwargs = {} + _test_function( + "kornia.color.ycbcr_to_rgb", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_xyz_to_rgb(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 5, 5),) + trace_kwargs = {} + test_args = (torch.rand(5, 3, 5, 5),) + test_kwargs = {} + _test_function( + "kornia.color.xyz_to_rgb", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_raw_to_rgb_2x2_downscaled(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 1, 4, 6), + kornia.color.CFA.RG, + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 1, 4, 6), + kornia.color.CFA.RG, + ) + test_kwargs = {} + _test_function( + "kornia.color.raw_to_rgb_2x2_downscaled", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_sepia(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 4, 4),) + trace_kwargs = { + "rescale": True, + "eps": 1e-6, + } + test_args = (torch.rand(5, 3, 4, 4),) + test_kwargs = { + "rescale": True, + "eps": 1e-6, + } + _test_function( + "kornia.color.sepia", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_combine_tensor_patches(target_framework, backend_compile): + trace_args = ( + kornia.contrib.extract_tensor_patches( + torch.arange(16).view(1, 1, 4, 4), + window_size=(2, 2), + stride=(2, 2), + ), + ) + trace_kwargs = { + "original_size": (4, 4), + "window_size": (2, 2), + "stride": (2, 2), + } + test_args = ( + kornia.contrib.extract_tensor_patches( + torch.flip(torch.arange(32), (0,)).view(2, 1, 4, 4), + window_size=(2, 2), + stride=(2, 2), + ), + ) + test_kwargs = { + "original_size": (4, 4), + "window_size": (2, 2), + "stride": (2, 2), + } + _test_function( + "kornia.contrib.combine_tensor_patches", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_adjust_contrast_with_mean_subtraction(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 1, 2, 2), + 2.0, + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 1, 2, 2), + 0.5, + ) + test_kwargs = {} + _test_function( + "kornia.enhance.adjust_contrast_with_mean_subtraction", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_posterize(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 1, 2, 2), + 3, + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 1, 2, 2), + 4, + ) + test_kwargs = {} + _test_function( + "kornia.enhance.posterize", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_image_histogram2d(target_framework, backend_compile): + trace_args = (torch.rand(1, 1, 10, 10),) + trace_kwargs = { + "min": 0.0, + "max": 255.0, + "n_bins": 256, + "bandwidth": None, + "centers": None, + "return_pdf": False, + "kernel": "triangular", + "eps": 1e-10, + } + test_args = (torch.rand(5, 1, 10, 10),) + test_kwargs = { + "min": 0.0, + "max": 255.0, + "n_bins": 256, + "bandwidth": None, + "centers": None, + "return_pdf": False, + "kernel": "triangular", + "eps": 1e-10, + } + _test_function( + "kornia.enhance.image_histogram2d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_normalize_min_max(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 4, 4), 0.0, 1.0) + trace_kwargs = {} + test_args = (torch.rand(5, 3, 4, 4), -1.0, 1.0) + test_kwargs = {} + _test_function( + "kornia.enhance.normalize_min_max", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_normalize_laf(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 5, 2, 3), + torch.rand(1, 3, 32, 32), + ) + trace_kwargs = {} + test_args = ( + torch.rand(2, 5, 2, 3), + torch.rand(2, 3, 64, 64), + ) + test_kwargs = {} + _test_function( + "kornia.feature.normalize_laf", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_laf_to_boundary_points(target_framework, backend_compile): + trace_args = (torch.rand(1, 5, 2, 3),) + trace_kwargs = {"n_pts": 50} + test_args = (torch.rand(2, 5, 2, 3),) + test_kwargs = {"n_pts": 100} + _test_function( + "kornia.feature.laf_to_boundary_points", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_ellipse_to_laf(target_framework, backend_compile): + trace_args = (torch.rand(1, 10, 5),) + trace_kwargs = {} + test_args = (torch.rand(2, 10, 5),) + test_kwargs = {} + _test_function( + "kornia.feature.ellipse_to_laf", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_make_upright(target_framework, backend_compile): + trace_args = (torch.rand(1, 5, 2, 3),) + trace_kwargs = {"eps": 1e-9} + test_args = (torch.rand(2, 5, 2, 3),) + test_kwargs = {"eps": 1e-6} + _test_function( + "kornia.feature.make_upright", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_rotate_laf(target_framework, backend_compile): + trace_args = ( + torch.randn((1, 5, 2, 3)), + torch.randn((1, 5, 1)), + ) + trace_kwargs = {} + test_args = ( + torch.randn((2, 10, 2, 3)), + torch.randn((2, 10, 1)), + ) + test_kwargs = {} + _test_function( + "kornia.feature.rotate_laf", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_laf_from_center_scale_ori(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 5, 2), + torch.randn(1, 5, 1, 1), + torch.randn(1, 5, 1), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 10, 2), + torch.randn(5, 10, 1, 1), + torch.randn(5, 10, 1), + ) + test_kwargs = {} + _test_function( + "kornia.feature.laf_from_center_scale_ori", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_laf_to_three_points(target_framework, backend_compile): + trace_args = (torch.rand(1, 5, 2, 3),) + trace_kwargs = {} + test_args = (torch.rand(2, 10, 2, 3),) + test_kwargs = {} + _test_function( + "kornia.feature.laf_to_three_points", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_get_gaussian_kernel2d(target_framework, backend_compile): + trace_args = ((5, 5), (1.5, 1.5)) + trace_kwargs = {} + test_args = ((3, 5), (1.5, 1.5)) + test_kwargs = {} + _test_function( + "kornia.filters.get_gaussian_kernel2d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_get_hanning_kernel2d(target_framework, backend_compile): + trace_args = ((4, 4),) + trace_kwargs = {} + test_args = ((8, 8),) + test_kwargs = {} + _test_function( + "kornia.filters.get_hanning_kernel2d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_get_laplacian_kernel2d(target_framework, backend_compile): + trace_args = (3,) + trace_kwargs = {} + test_args = (5,) + test_kwargs = {} + _test_function( + "kornia.filters.get_laplacian_kernel2d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_charbonnier_loss(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 32, 32), + torch.rand(1, 3, 32, 32), + ) + trace_kwargs = {"reduction": "none"} + test_args = ( + torch.rand(5, 3, 32, 32), + torch.rand(5, 3, 32, 32), + ) + test_kwargs = {"reduction": "none"} + _test_function( + "kornia.losses.charbonnier_loss", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_geman_mcclure_loss(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 32, 32), + torch.rand(1, 3, 32, 32), + ) + trace_kwargs = {"reduction": "none"} + test_args = ( + torch.rand(5, 3, 32, 32), + torch.rand(5, 3, 32, 32), + ) + test_kwargs = {"reduction": "none"} + _test_function( + "kornia.losses.geman_mcclure_loss", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_confusion_matrix(target_framework, backend_compile): + trace_args = ( + torch.tensor([0, 1, 0]), + torch.tensor([0, 1, 0]), + 3, + ) + trace_kwargs = {} + test_args = ( + torch.tensor([0, 1, 2]), + torch.tensor([0, 2, 1]), + 3, + ) + test_kwargs = {} + _test_function( + "kornia.metrics.confusion_matrix", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_mean_iou_bbox(target_framework, backend_compile): + trace_args = ( + torch.tensor([[40, 40, 60, 60], [30, 40, 50, 60]]), + torch.tensor([[40, 50, 60, 70], [30, 40, 40, 50]]), + ) + trace_kwargs = {} + test_args = ( + torch.tensor([[20, 20, 40, 40], [10, 30, 30, 50]]), + torch.tensor([[20, 30, 40, 50], [10, 20, 20, 30]]), + ) + test_kwargs = {} + _test_function( + "kornia.metrics.mean_iou_bbox", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_dilation(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 5, 5), + torch.rand(3, 3), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 3, 5, 5), + torch.rand(3, 3), + ) + test_kwargs = {} + _test_function( + "kornia.morphology.dilation", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_opening(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 5, 5), + torch.rand(3, 3), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 3, 5, 5), + torch.rand(3, 3), + ) + test_kwargs = {} + _test_function( + "kornia.morphology.opening", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_gradient(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 5, 5), + torch.rand(3, 3), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 3, 5, 5), + torch.rand(3, 3), + ) + test_kwargs = {} + _test_function( + "kornia.morphology.gradient", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_top_hat(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 5, 5), + torch.rand(3, 3), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 3, 5, 5), + torch.rand(3, 3), + ) + test_kwargs = {} + _test_function( + "kornia.morphology.top_hat", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_create_meshgrid3d(target_framework, backend_compile): + trace_args = (2, 2, 2) + trace_kwargs = {} + test_args = (4, 4, 4) + test_kwargs = {} + _test_function( + "kornia.utils.create_meshgrid3d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_bbox_generator3d(target_framework, backend_compile): + trace_args = ( + torch.tensor([0, 3]), + torch.tensor([1, 4]), + torch.tensor([2, 5]), + torch.tensor([10, 40]), + torch.tensor([20, 50]), + torch.tensor([30, 60]), + ) + trace_kwargs = {} + test_args = ( + torch.tensor([5, 8]), + torch.tensor([6, 7]), + torch.tensor([9, 11]), + torch.tensor([15, 20]), + torch.tensor([25, 30]), + torch.tensor([35, 45]), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.bbox.bbox_generator3d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_infer_bbox_shape3d(target_framework, backend_compile): + trace_args = ( + torch.tensor( + [ + [ + [0, 1, 2], + [10, 1, 2], + [10, 21, 2], + [0, 21, 2], + [0, 1, 32], + [10, 1, 32], + [10, 21, 32], + [0, 21, 32], + ] + ] + ), + ) + trace_kwargs = {} + test_args = ( + torch.tensor( + [ + [ + [3, 4, 5], + [43, 4, 5], + [43, 54, 5], + [3, 54, 5], + [3, 4, 65], + [43, 4, 65], + [43, 54, 65], + [3, 54, 65], + ] + ] + ), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.bbox.infer_bbox_shape3d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_undistort_image(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 5, 5), + torch.eye(3)[None], + torch.rand(1, 4), + ) + trace_kwargs = {} + test_args = ( + torch.rand(1, 3, 10, 10), + torch.eye(3)[None], + torch.rand(1, 4), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.calibration.undistort_image", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_distort_points(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 1, 2), + torch.eye(3)[None], + torch.rand(1, 4), + ) + trace_kwargs = {} + test_args = ( + torch.rand(1, 3, 2), + torch.eye(3)[None], + torch.rand(1, 4), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.calibration.distort_points", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_tilt_projection(target_framework, backend_compile): + trace_args = ( + torch.tensor(0.1), + torch.tensor(0.2), + ) + trace_kwargs = {"return_inverse": False} + test_args = ( + torch.tensor(0.3), + torch.tensor(0.4), + ) + test_kwargs = {"return_inverse": False} + _test_function( + "kornia.geometry.calibration.tilt_projection", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_project_points_orthographic(target_framework, backend_compile): + trace_args = (torch.rand(2, 3),) + trace_kwargs = {} + test_args = (torch.rand(5, 3),) + test_kwargs = {} + _test_function( + "kornia.geometry.camera.project_points_orthographic", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_undistort_points_kannala_brandt(target_framework, backend_compile): + trace_args = ( + torch.rand(2, 2), + torch.rand(2, 8), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 2), + torch.rand(5, 8), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.camera.undistort_points_kannala_brandt", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_deg2rad(target_framework, backend_compile): + trace_args = (torch.tensor(180.0),) + trace_kwargs = {} + test_args = (torch.rand(5, 3, 3),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.deg2rad", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_cart2pol(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 3), torch.rand(1, 3, 3)) + trace_kwargs = {"eps": 1.0e-8} + test_args = (torch.rand(5, 3, 3), torch.rand(5, 3, 3)) + test_kwargs = {"eps": 1.0e-8} + _test_function( + "kornia.geometry.conversions.cart2pol", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_angle_to_rotation_matrix(target_framework, backend_compile): + trace_args = (torch.rand(1, 3),) + trace_kwargs = {} + test_args = (torch.rand(5, 3),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.angle_to_rotation_matrix", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_convert_points_from_homogeneous(target_framework, backend_compile): + trace_args = (torch.rand(1, 3),) + trace_kwargs = {} + test_args = (torch.rand(5, 3),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.convert_points_from_homogeneous", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_convert_affinematrix_to_homography(target_framework, backend_compile): + trace_args = (torch.rand(1, 2, 3),) + trace_kwargs = {} + test_args = (torch.rand(5, 2, 3),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.convert_affinematrix_to_homography", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_denormalize_pixel_coordinates(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 2), + 64, + 64, + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 2), + 128, + 128, + ) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.denormalize_pixel_coordinates", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_normalize_pixel_coordinates3d(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3), + 32, + 64, + 64, + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 3), + 64, + 128, + 128, + ) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.normalize_pixel_coordinates3d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_normalize_homography3d(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 4, 4), + (8, 32, 32), + (16, 64, 64), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 4, 4), + (8, 32, 32), + (16, 64, 64), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.normalize_homography3d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_quaternion_to_axis_angle(target_framework, backend_compile): + trace_args = (torch.randn(1, 4),) + trace_kwargs = {} + test_args = (torch.randn(5, 4),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.quaternion_to_axis_angle", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_quaternion_to_rotation_matrix(target_framework, backend_compile): + trace_args = (torch.randn(1, 4),) + trace_kwargs = {} + test_args = (torch.randn(5, 4),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.quaternion_to_rotation_matrix", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_quaternion_log_to_exp(target_framework, backend_compile): + trace_args = (torch.randn(1, 3),) + trace_kwargs = {"eps": 1.0e-12} + test_args = (torch.randn(5, 3),) + test_kwargs = {"eps": 1.0e-12} + _test_function( + "kornia.geometry.conversions.quaternion_log_to_exp", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_vector_to_skew_symmetric_matrix(target_framework, backend_compile): + trace_args = (torch.tensor([1.0, 2.0, 3.0]),) + trace_kwargs = {} + test_args = (torch.tensor([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.vector_to_skew_symmetric_matrix", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_rotation_matrix_to_axis_angle(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 3),) + trace_kwargs = {} + test_args = (torch.rand(5, 3, 3),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.rotation_matrix_to_axis_angle", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_axis_angle_to_rotation_matrix(target_framework, backend_compile): + trace_args = (torch.tensor([[0.0, 0.0, 0.0], [1.5708, 0.0, 0.0]]),) + trace_kwargs = {} + test_args = (torch.tensor([[0.0, 0.0, 0.0], [1.5708, 0.0, 0.0]]),) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.axis_angle_to_rotation_matrix", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_quaternion_from_euler(target_framework, backend_compile): + trace_args = ( + torch.tensor(0.0), + torch.tensor(0.0), + torch.tensor(0.0), + ) + trace_kwargs = {} + test_args = ( + torch.tensor([0.0, 1.0, 2.0]), + torch.tensor([2.0, 1.0, 0.0]), + torch.tensor([1.0, 2.0, 0.0]), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.quaternion_from_euler", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_Rt_to_matrix4x4(target_framework, backend_compile): + trace_args = ( + torch.randn(1, 3, 3), + torch.rand(1, 3, 1), + ) + trace_kwargs = {} + test_args = ( + torch.randn(5, 3, 3), + torch.rand(5, 3, 1), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.Rt_to_matrix4x4", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_worldtocam_to_camtoworld_Rt(target_framework, backend_compile): + trace_args = ( + torch.randn(1, 3, 3), + torch.rand(1, 3, 1), + ) + trace_kwargs = {} + test_args = ( + torch.randn(5, 3, 3), + torch.rand(5, 3, 1), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.worldtocam_to_camtoworld_Rt", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_ARKitQTVecs_to_ColmapQTVecs(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 4), + torch.rand(1, 3, 1), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 4), + torch.rand(5, 3, 1), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.conversions.ARKitQTVecs_to_ColmapQTVecs", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_unproject_meshgrid(target_framework, backend_compile): + trace_args = ( + 4, + 4, + torch.eye(3), + ) + trace_kwargs = {"normalize_points": False, "device": "cpu", "dtype": torch.float32} + test_args = ( + 5, + 5, + torch.eye(3), + ) + test_kwargs = {"normalize_points": False, "device": "cpu", "dtype": torch.float32} + _test_function( + "kornia.geometry.depth.unproject_meshgrid", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_warp_frame_depth(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 4, 4), + torch.rand(1, 1, 4, 4), + torch.eye(4)[None], + torch.eye(3)[None], + ) + trace_kwargs = {"normalize_points": False} + test_args = ( + torch.rand(5, 3, 5, 5), + torch.rand(5, 1, 5, 5), + torch.eye(4)[None].repeat(5, 1, 1), + torch.eye(3)[None].repeat(5, 1, 1), + ) + test_kwargs = {"normalize_points": False} + _test_function( + "kornia.geometry.depth.warp_frame_depth", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_essential_from_fundamental(target_framework, backend_compile): + trace_args = ( + torch.rand(3, 3), + torch.rand(3, 3), + torch.rand(3, 3), + ) + trace_kwargs = {} + test_args = ( + torch.rand(3, 3), + torch.rand(3, 3), + torch.rand(3, 3), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.epipolar.essential_from_fundamental", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_relative_camera_motion(target_framework, backend_compile): + trace_args = ( + torch.rand(3, 3), + torch.rand(3, 1), + torch.rand(3, 3), + torch.rand(3, 1), + ) + trace_kwargs = {} + test_args = ( + torch.rand(3, 3), + torch.rand(3, 1), + torch.rand(3, 3), + torch.rand(3, 1), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.epipolar.relative_camera_motion", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_compute_correspond_epilines(target_framework, backend_compile): + trace_args = ( + torch.rand(2, 8, 2), + torch.rand(2, 3, 3), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 8, 2), + torch.rand(5, 3, 3), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.epipolar.compute_correspond_epilines", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_get_perpendicular(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 2, 3), + torch.rand(1, 2, 2), + ) + trace_kwargs = {} + test_args = ( + torch.rand(2, 5, 3), + torch.rand(2, 5, 2), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.epipolar.get_perpendicular", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_sampson_epipolar_distance(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 4, 2), + torch.rand(1, 4, 2), + torch.rand(1, 3, 3), + ) + trace_kwargs = {"squared": True, "eps": 1e-8} + test_args = ( + torch.rand(5, 4, 2), + torch.rand(5, 4, 2), + torch.rand(5, 3, 3), + ) + test_kwargs = {"squared": True, "eps": 1e-8} + _test_function( + "kornia.geometry.epipolar.sampson_epipolar_distance", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_left_to_right_epipolar_distance(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 4, 2), + torch.rand(1, 4, 2), + torch.rand(1, 3, 3), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 4, 2), + torch.rand(5, 4, 2), + torch.rand(5, 3, 3), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.epipolar.left_to_right_epipolar_distance", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_intrinsics_like(target_framework, backend_compile): + trace_args = (0.5, torch.rand(1, 3, 256, 256)) + trace_kwargs = {} + test_args = (0.8, torch.rand(2, 3, 256, 256)) + test_kwargs = {} + _test_function( + "kornia.geometry.epipolar.intrinsics_like", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_cross_product_matrix(target_framework, backend_compile): + trace_args = (torch.rand(1, 3),) + trace_kwargs = {} + test_args = (torch.rand(5, 3),) + test_kwargs = {} + _test_function( + "kornia.geometry.epipolar.cross_product_matrix", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_inverse_transformation(target_framework, backend_compile): + trace_args = (torch.rand(1, 4, 4),) + trace_kwargs = {} + test_args = (torch.rand(5, 4, 4),) + test_kwargs = {} + _test_function( + "kornia.geometry.linalg.inverse_transformation", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_batched_dot_product(target_framework, backend_compile): + trace_args = ( + torch.rand(3, 5), + torch.rand(3, 5), + ) + trace_kwargs = {"keepdim": False} + test_args = ( + torch.rand(5, 3, 5), + torch.rand(5, 3, 5), + ) + test_kwargs = {"keepdim": False} + _test_function( + "kornia.geometry.linalg.batched_dot_product", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_multiply_deg_two_one_poly(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 20), + torch.rand(1, 20), + ) + trace_kwargs = {} + test_args = ( + torch.rand(3, 20), + torch.rand(3, 20), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.solvers.multiply_deg_two_one_poly", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_determinant_to_polynomial(target_framework, backend_compile): + trace_args = (torch.rand(1, 3, 13),) + trace_kwargs = {} + test_args = (torch.rand(5, 3, 13),) + test_kwargs = {} + _test_function( + "kornia.geometry.solvers.determinant_to_polynomial", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_spatial_soft_argmax2d(target_framework, backend_compile): + trace_args = (torch.rand(1, 1, 5, 5),) + trace_kwargs = { + "temperature": torch.tensor(1.0), + "normalized_coordinates": True, + } + test_args = (torch.rand(10, 1, 5, 5),) + test_kwargs = { + "temperature": torch.tensor(0.5), + "normalized_coordinates": True, + } + _test_function( + "kornia.geometry.subpix.spatial_soft_argmax2d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_render_gaussian2d(target_framework, backend_compile): + trace_args = ( + torch.tensor([[1.0, 1.0]]), + torch.tensor([[1.0, 1.0]]), + (5, 5), + ) + trace_kwargs = { + "normalized_coordinates": False, + } + test_args = ( + torch.tensor([[2.0, 2.0]]), + torch.tensor([[0.5, 0.5]]), + (10, 10), + ) + test_kwargs = { + "normalized_coordinates": False, + } + _test_function( + "kornia.geometry.subpix.render_gaussian2d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_nms3d(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 1, 5, 5, 5), + (3, 3, 3), + ) + trace_kwargs = { + "mask_only": False, + } + test_args = ( + torch.rand(10, 1, 5, 5, 5), + (3, 3, 3), + ) + test_kwargs = { + "mask_only": False, + } + _test_function( + "kornia.geometry.subpix.nms3d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_warp_points_tps(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 5, 2), + torch.rand(1, 5, 2), + torch.rand(1, 5, 2), + torch.rand(1, 3, 2), + ) + trace_kwargs = {} + test_args = ( + torch.rand(5, 10, 2), + torch.rand(5, 10, 2), + torch.rand(5, 10, 2), + torch.rand(5, 3, 2), + ) + test_kwargs = {} + _test_function( + "kornia.geometry.transform.warp_points_tps", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_remap(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 5, 5), + torch.rand(1, 5, 5), + torch.rand(1, 5, 5), + ) + trace_kwargs = { + "mode": "bilinear", + "padding_mode": "zeros", + "align_corners": None, + "normalized_coordinates": False, + } + test_args = ( + torch.rand(1, 3, 10, 10), + torch.rand(1, 10, 10), + torch.rand(1, 10, 10), + ) + test_kwargs = { + "mode": "bilinear", + "padding_mode": "zeros", + "align_corners": None, + "normalized_coordinates": False, + } + _test_function( + "kornia.geometry.transform.remap", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_get_rotation_matrix2d(target_framework, backend_compile): + trace_args = (torch.rand(1, 2), 45.0 * torch.ones(1), torch.rand(1, 2)) + trace_kwargs = {} + test_args = (torch.rand(1, 2), 90.0 * torch.ones(1), 2.0 * torch.ones(1, 2)) + test_kwargs = {} + _test_function( + "kornia.geometry.transform.get_rotation_matrix2d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_get_shear_matrix2d(target_framework, backend_compile): + trace_args = (torch.tensor([[0.0, 0.0]]), torch.tensor([1.0]), torch.tensor([0.5])) + trace_kwargs = {} + test_args = (torch.tensor([[1.0, 1.0]]), torch.tensor([1.5]), torch.tensor([0.75])) + test_kwargs = {} + _test_function( + "kornia.geometry.transform.get_shear_matrix2d", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_invert_affine_transform(target_framework, backend_compile): + trace_args = (torch.rand(1, 2, 3),) + trace_kwargs = {} + test_args = (torch.rand(5, 2, 3),) + test_kwargs = {} + _test_function( + "kornia.geometry.transform.invert_affine_transform", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) + + +def test_crop_by_indices(target_framework, backend_compile): + trace_args = ( + torch.rand(1, 3, 64, 64), + torch.tensor([[[10, 10], [50, 10], [50, 50], [10, 50]]], dtype=torch.float32), + ) + trace_kwargs = {"size": (40, 40), "interpolation": "bilinear"} + test_args = ( + torch.rand(5, 3, 64, 64), + torch.tensor( + [[[10, 10], [50, 10], [50, 50], [10, 50]]] * 5, dtype=torch.float32 + ), + ) + test_kwargs = {"size": (40, 40), "interpolation": "bilinear"} + _test_function( + "kornia.geometry.transform.crop_by_indices", + trace_args, + trace_kwargs, + test_args, + test_kwargs, + target_framework, + backend_compile=backend_compile, + tolerance=1e-3, + ) diff --git a/ivy_tests/test_ivy/conftest.py b/ivy_tests/test_ivy/conftest.py index 9cb8e15586fb8..13731b6f5eb4e 100644 --- a/ivy_tests/test_ivy/conftest.py +++ b/ivy_tests/test_ivy/conftest.py @@ -290,10 +290,18 @@ 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 @@ -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 7f21c0bc413ab..b53be84b2fce0 100644 --- a/ivy_tests/test_ivy/helpers/function_testing.py +++ b/ivy_tests/test_ivy/helpers/function_testing.py @@ -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, @@ -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 = [] @@ -727,9 +796,8 @@ def test_frontend_function( 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 @@ -773,6 +845,12 @@ def test_frontend_function( if test_flags.with_copy is True: test_flags.with_out = False test_flags.inplace = False + if test_flags.test_trace or test_flags.test_trace_each: + test_flags.with_out = 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( @@ -864,8 +942,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 +1005,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 +1025,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 +1054,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 +1184,7 @@ def test_gradient_backend_computation( on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ): @@ -1117,6 +1210,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 +1241,7 @@ def test_gradient_ground_truth_computation( test_flags, kwargs_idxs, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ): @@ -1180,6 +1275,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,6 +1304,7 @@ def gradient_test( input_dtypes, test_flags, test_trace: bool = False, + test_trace_each: bool = False, rtol_: Optional[float] = None, atol_: float = 1e-06, tolerance_dict=None, @@ -1239,6 +1336,7 @@ def gradient_test( on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -1259,6 +1357,7 @@ def gradient_test( on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -1282,6 +1381,7 @@ def gradient_test( test_flags, kwargs_idxs, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -1302,6 +1402,7 @@ def gradient_test( test_flags, kwargs_idxs, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -1335,6 +1436,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 +1586,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 +1627,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 +1669,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, ) @@ -1607,14 +1712,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 +1779,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 +1816,7 @@ def test_method( method_name, init_with_v, test_trace, + test_trace_each, method_with_v, ) ) @@ -1753,6 +1861,7 @@ def test_method( method_name, init_with_v, test_trace, + test_trace_each, method_with_v, ) @@ -1777,6 +1886,7 @@ def test_method( class_name, method_name, test_trace, + test_trace_each, v_np, ) ) @@ -1807,6 +1917,7 @@ def test_method( class_name, method_name, test_trace, + test_trace_each, v_np, ) @@ -1842,6 +1953,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 +1974,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, @@ -1921,9 +2034,8 @@ def test_frontend_method( 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 +2076,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 +2251,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 +2374,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 +2404,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 +2475,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,19 +2559,31 @@ 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): ret = fn(*args, **kwargs) + if test_trace or test_trace_each: + ret = ivy_backend.to_ivy(ret, True) def map_fn(x): if _is_frontend_array(x): @@ -2479,19 +2603,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 +2659,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 fe9eb99c44bdb..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 ---------- @@ -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 31742e5519501..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 ---------- @@ -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 971a19bdee0b2..a6f86024384b2 100644 --- a/ivy_tests/test_ivy/helpers/hypothesis_helpers/general_helpers.py +++ b/ivy_tests/test_ivy/helpers/hypothesis_helpers/general_helpers.py @@ -14,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. @@ -62,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 ---------- @@ -165,7 +163,7 @@ def general_helpers_dtype_info_helper(backend, kind_dtype, dtype): # from array-api repo class BroadcastError(ValueError): - """Shapes do not broadcast with eachother.""" + """Shapes do not broadcast with each other.""" # from array-api repo @@ -225,8 +223,8 @@ def two_broadcastable_shapes(draw): # 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 ---------- @@ -254,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 ---------- @@ -282,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 ---------- @@ -331,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 ---------- @@ -355,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 ---------- @@ -402,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 ---------- @@ -517,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 ---------- @@ -614,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 ---------- @@ -655,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 39234c644de27..47ee2c1dcaccf 100644 --- a/ivy_tests/test_ivy/helpers/multiprocessing.py +++ b/ivy_tests/test_ivy/helpers/multiprocessing.py @@ -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,6 +194,7 @@ def backend_proc(input_queue, output_queue): on_device, fn, test_trace, + test_trace_each, xs_grad_idxs, ret_grad_idxs, ) @@ -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 4d20d861e1f17..36d01f0d5892e 100644 --- a/ivy_tests/test_ivy/helpers/testing_helpers.py +++ b/ivy_tests/test_ivy/helpers/testing_helpers.py @@ -7,7 +7,7 @@ import functools 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 ---------- @@ -91,9 +93,8 @@ def num_positional_args_method(draw, *, method): @st.composite 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. + """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 ---------- @@ -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): @@ -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), @@ -630,6 +640,7 @@ def handle_method( 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/test_jax/test__src/test_tree_util.py b/ivy_tests/test_ivy/test_frontends/test_jax/test__src/test_tree_util.py index 5a53c51bd5196..171cf37f2d825 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test__src/test_tree_util.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test__src/test_tree_util.py @@ -87,14 +87,16 @@ def tree_strategy(max_depth=2): return leaf_strategy() else: return st.dictionaries( - keys=st.one_of(*[ - st.text( - alphabet=st.characters(min_codepoint=97, max_codepoint=122), - min_size=1, - max_size=1, - ).filter(lambda x: x not in used_keys) - for used_keys in [set()] - ]), + keys=st.one_of( + *[ + st.text( + alphabet=st.characters(min_codepoint=97, max_codepoint=122), + min_size=1, + max_size=1, + ).filter(lambda x: x not in used_keys) + for used_keys in [set()] + ] + ), values=st.one_of(leaf_strategy(), tree_strategy(max_depth - 1)), min_size=1, max_size=10, 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 8fa019823c2c0..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 @@ -208,15 +208,13 @@ def dtype_x_axis(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, @@ -224,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, @@ -232,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, @@ -244,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, @@ -261,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, @@ -278,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, @@ -296,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, @@ -314,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, @@ -328,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, @@ -336,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, @@ -348,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, @@ -360,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, @@ -380,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, @@ -392,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, @@ -400,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, @@ -409,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, @@ -428,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, @@ -449,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, @@ -465,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, @@ -473,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, @@ -485,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, @@ -501,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, @@ -509,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, @@ -521,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, @@ -537,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, @@ -546,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, @@ -558,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, @@ -575,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, @@ -590,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, @@ -602,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, @@ -610,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, @@ -622,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, @@ -639,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, @@ -659,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, @@ -676,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, @@ -695,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, @@ -707,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, @@ -727,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, @@ -739,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, @@ -759,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, @@ -775,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, @@ -783,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, @@ -795,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, @@ -811,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, @@ -832,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, @@ -848,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, @@ -887,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, @@ -896,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, @@ -908,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, @@ -922,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, @@ -930,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, @@ -942,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, @@ -978,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, @@ -993,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, @@ -1002,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, @@ -1016,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, @@ -1031,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, @@ -1054,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, @@ -1069,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, @@ -1078,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, @@ -1092,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, @@ -1107,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, @@ -1116,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, @@ -1130,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, @@ -1146,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, @@ -1154,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, @@ -1168,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, @@ -1184,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, @@ -1192,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, @@ -1206,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, @@ -1220,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, @@ -1240,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, @@ -1256,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, @@ -1276,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, @@ -1290,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, @@ -1326,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, @@ -1334,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, @@ -1348,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, @@ -1364,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, @@ -1384,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, @@ -1420,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, @@ -1432,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, @@ -1454,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, @@ -1470,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, @@ -1497,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, 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 f355a902382ea..8c0d6f6e0f7c6 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 @@ -460,24 +460,30 @@ def _x_and_filters(draw, dim=2, transpose=False, general=False): dim_num_st2 = st.sampled_from(["OIDHW", "DHWIO"]) dim_seq = [*range(0, dim + 2)] dimension_numbers = draw( - st.sampled_from([ - None, - (draw(dim_num_st1), draw(dim_num_st2), draw(dim_num_st1)), - ConvDimensionNumbers( - *map( - tuple, - draw( - st.lists(st.permutations(dim_seq), min_size=3, max_size=3) - ), - ) - ), - ]) + st.sampled_from( + [ + None, + (draw(dim_num_st1), draw(dim_num_st2), draw(dim_num_st1)), + ConvDimensionNumbers( + *map( + tuple, + draw( + st.lists( + st.permutations(dim_seq), min_size=3, max_size=3 + ) + ), + ) + ), + ] + ) ) else: 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: @@ -2260,6 +2266,7 @@ def test_jax_mul( available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True, + abs_smallest_val=1e-07, ), test_with_out=st.just(False), ) diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_dtype.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_dtype.py index fa70990928744..216663c31c254 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_dtype.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_dtype.py @@ -4,6 +4,36 @@ # local import ivy_tests.test_ivy.helpers as helpers from ivy_tests.test_ivy.helpers.testing_helpers import handle_frontend_test +from ivy_tests.test_ivy.test_functional.test_core.test_statistical import ( + _get_castable_dtype, +) + + +@handle_frontend_test( + fn_tree="jax.numpy.astype", + dtype_and_x=_get_castable_dtype(), + test_with_out=st.just(False), +) +def test_jax_astype( + dtype_and_x, + fn_tree, + test_flags, + on_device, + frontend, + backend_fw, +): + input_dtype, x, _, castable_dtype = 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, + x=x, + dtype=castable_dtype, + ) # can_cast diff --git a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_fft.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_fft.py index 1030839ae8e07..8b25279a3aadb 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_fft.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/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_jax, +) # fft @@ -242,6 +245,109 @@ def test_jax_numpy_ifft2( ) +@handle_frontend_test( + fn_tree="jax.numpy.fft.ifftn", + dtype_and_x=_x_and_ifftn_jax(), +) +def test_jax_numpy_ifftn( + dtype_and_x, backend_fw, frontend, test_flags, fn_tree, on_device +): + input_dtype, x, s, axes, norm = 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, + test_values=True, + atol=1e-09, + rtol=1e-08, + a=x, + s=s, + axes=axes, + norm=norm, + ) + + +# ifftshift +@handle_frontend_test( + fn_tree="jax.numpy.fft.ifftshift", + dtype_values_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=1, + min_value=-1e5, + max_value=1e5, + min_num_dims=1, + max_num_dims=5, + min_dim_size=1, + max_dim_size=5, + allow_inf=False, + large_abs_safety_factor=2.5, + small_abs_safety_factor=2.5, + safety_factor_scale="log", + valid_axis=True, + force_int_axis=True, + ), +) +def test_jax_numpy_ifftshift( + dtype_values_axis, backend_fw, frontend, test_flags, fn_tree, on_device +): + dtype, values, axis = dtype_values_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=True, + x=values[0], + axes=axis, + ) + + +# irfftn +@handle_frontend_test( + fn_tree="jax.numpy.fft.irfftn", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("numeric"), + min_value=-10, + max_value=10, + min_num_dims=1, + max_num_dims=3, + min_dim_size=2, + max_dim_size=10, + valid_axis=True, + force_int_axis=True, + num_arrays=1, + ), + norm=st.sampled_from(["backward", "ortho", "forward"]), +) +def test_jax_numpy_irfftn( + dtype_x_axis, + norm, + frontend, + test_flags, + fn_tree, + backend_fw, +): + input_dtypes, x, _ = dtype_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, + atol=1e-3, + a=x[0], + s=None, # TODO: also test cases where `s` and `axes` are not None + axes=None, + norm=norm, + ) + + # rfft @handle_frontend_test( fn_tree="jax.numpy.fft.rfft", 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 5ebef754a9aab..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): @@ -113,9 +101,9 @@ def test_jax_choose( on_device, ): dtypes, x, indices, axis, _ = dtype_x_indices_axis - choices = ivy.array([ - np.random.randint(0, 10, size=x.shape) for _ in range(len(dtypes)) - ]) + choices = ivy.array( + [np.random.randint(0, 10, size=x.shape) for _ in range(len(dtypes))] + ) helpers.test_frontend_function( input_dtypes=dtypes, backend_to_test=backend_fw, @@ -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 721dd7e1fcf70..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 @@ -39,9 +39,9 @@ def _get_inv_square_matrices(draw): ) shape, ind = draw( - st.sampled_from([ - (generated_shape, generated_ind), (handpicked_shape, handpicked_ind) - ]) + st.sampled_from( + [(generated_shape, generated_ind), (handpicked_shape, handpicked_ind)] + ) ) input_dtype = draw( @@ -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_logic.py b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_logic.py index f9a2a8c0a8f09..1fdcc0c6f6a35 100644 --- a/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_logic.py +++ b/ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_logic.py @@ -1108,6 +1108,37 @@ def test_jax_not_equal( ) +# unpackbits +@handle_frontend_test( + fn_tree="jax.numpy.unpackbits", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=1, + min_dim_size=1, + valid_axis=True, + max_axes_size=1, + force_int_axis=True, + ), + test_with_out=st.just(False), + bitorder=st.sampled_from(["big", "little"]), +) +def test_jax_numpy_unpackbits( + dtype_x_axis, bitorder, frontend, on_device, *, fn_tree, test_flags, backend_fw +): + input_dtype, x, axis = dtype_x_axis + helpers.test_frontend_function( + input_dtypes=input_dtype, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + axis=axis, + bitorder=bitorder, + backend_to_test=backend_fw, + ) + + # packbits @handle_frontend_test( fn_tree="jax.numpy.packbits", 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 92b3a644c42bb..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 @@ -111,19 +111,21 @@ def _get_input_and_block(draw): max_size=10, ) ) - x_dtypes, xs = zip(*[ - draw( - helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), - min_num_dims=1, - max_num_dims=5, - min_dim_size=2, - max_dim_size=10, - shape=shape, + x_dtypes, xs = zip( + *[ + draw( + helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + min_num_dims=1, + max_num_dims=5, + min_dim_size=2, + max_dim_size=10, + shape=shape, + ) ) - ) - for shape in shapes - ]) + for shape in shapes + ] + ) return x_dtypes, xs @@ -228,18 +230,20 @@ def _get_input_and_two_swapabble_axes(draw): @st.composite def _pad_helper(draw): mode = draw( - st.sampled_from([ - "constant", - "edge", - "linear_ramp", - "maximum", - "mean", - "median", - "minimum", - "reflect", - "symmetric", - "wrap", - ]) + st.sampled_from( + [ + "constant", + "edge", + "linear_ramp", + "maximum", + "mean", + "median", + "minimum", + "reflect", + "symmetric", + "wrap", + ] + ) ) if mode == "median": dtypes = "float" 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 7ff6a267a5b4b..71edafa650ca7 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 @@ -1103,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 @@ -3314,11 +3314,11 @@ def test_jax_trace( @handle_frontend_test( - fn_tree="jax.numpy.trapz", + fn_tree="jax.numpy.trapezoid", dtype_x_axis_rand_either=_either_x_dx(), test_with_out=st.just(False), ) -def test_jax_trapz( +def test_jax_trapezoid( *, dtype_x_axis_rand_either, on_device, @@ -3379,6 +3379,49 @@ def test_jax_trunc( ) +@handle_frontend_test( + fn_tree="jax.numpy.unwrap", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("numeric"), + min_num_dims=2, + max_num_dims=5, + min_dim_size=2, + max_dim_size=10, + min_value=-ivy.pi, + max_value=ivy.pi, + valid_axis=True, + force_int_axis=True, + ), + discont=st.floats(min_value=0, max_value=3.0), + period=st.floats(min_value=2 * np.pi, max_value=10.0), + test_with_out=st.just(False), +) +def test_jax_unwrap( + *, + dtype_x_axis, + on_device, + fn_tree, + frontend, + backend_fw, + test_flags, + discont, + period, +): + dtype, x, axis = dtype_x_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, + p=x[0], + discont=discont, + axis=axis, + period=period, + ) + + # vdot @handle_frontend_test( fn_tree="jax.numpy.vdot", 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 c972407723b23..8347f034fa564 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 @@ -546,17 +546,19 @@ def test_jax_cumsum( # einsum @handle_frontend_test( fn_tree="jax.numpy.einsum", - eq_n_op=st.sampled_from([ - ( - "ii", - np.arange(25).reshape(5, 5), - ), - ( - "ii->i", - np.arange(25).reshape(5, 5), - ), - ("ij,j", np.arange(25).reshape(5, 5), np.arange(5)), - ]), + eq_n_op=st.sampled_from( + [ + ( + "ii", + np.arange(25).reshape(5, 5), + ), + ( + "ii->i", + np.arange(25).reshape(5, 5), + ), + ("ij,j", np.arange(25).reshape(5, 5), np.arange(5)), + ] + ), dtype=helpers.get_dtypes("float", full=False), ) def test_jax_einsum( @@ -1006,6 +1008,32 @@ def test_jax_nanmin( ) +# nanpercentile +@handle_frontend_test( + fn_tree="jax.numpy.nanpercentile", + dtype_and_x=_percentile_helper(), + keep_dims=st.booleans(), + test_gradients=st.just(False), + test_with_out=st.just(False), +) +def test_jax_nanpercentile( + *, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_device +): + input_dtype, x, axis, interpolation, q = dtype_and_x + helpers.test_function( + input_dtypes=input_dtype, + test_flags=test_flags, + backend_to_test=backend_fw, + fn_name=fn_name, + on_device=on_device, + a=x[0], + q=q, + axis=axis, + interpolation=interpolation[0], + keepdims=keep_dims, + ) + + # nanstd @handle_frontend_test( fn_tree="jax.numpy.nanstd", @@ -1318,28 +1346,3 @@ def test_jax_var( atol=1e-3, rtol=1e-3, ) - - -@handle_frontend_test( - fn_tree="jax.numpy.nanpercentile", - dtype_and_x=_percentile_helper(), - keep_dims=st.booleans(), - test_gradients=st.just(False), - test_with_out=st.just(False), -) -def test_nanpercentile( - *, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_device -): - input_dtype, x, axis, interpolation, q = dtype_and_x - helpers.test_function( - input_dtypes=input_dtype, - test_flags=test_flags, - backend_to_test=backend_fw, - fn_name=fn_name, - on_device=on_device, - a=x[0], - q=q, - axis=axis, - interpolation=interpolation[0], - keepdims=keep_dims, - ) 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_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 8b07920b02287..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 @@ -356,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( @@ -529,15 +563,17 @@ def test_mindspore_flatten( num_arrays=1, shared_dtype=True, ), - mode=st.sampled_from([ - "nearest", - "linear", - "bilinear", - "bicubic", - "trilinear", - "area", - "nearest-exact", - ]), + mode=st.sampled_from( + [ + "nearest", + "linear", + "bilinear", + "bicubic", + "trilinear", + "area", + "nearest-exact", + ] + ), align_corners=st.booleans(), recompute_scale_factor=st.booleans(), size_and_scale_factor=_size_and_scale_factor_strategy(), 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 878ed7e54c44d..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 ---------- @@ -276,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 fc918a1d85da6..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 @@ -23,17 +23,23 @@ @st.composite def _dtype_helper(draw): return draw( - st.sampled_from([ - draw(st.sampled_from([int, float, bool])), - ivy.as_native_dtype( - draw(helpers.get_dtypes("valid", full=False, prune_function=False))[0] - ), - np_frontend.dtype( - draw(helpers.get_dtypes("valid", full=False, prune_function=False))[0] - ), - draw(st.sampled_from(list(np_frontend.numpy_scalar_to_dtype.keys()))), - draw(st.sampled_from(list(np_frontend.numpy_str_to_type_table.keys()))), - ]) + st.sampled_from( + [ + draw(st.sampled_from([int, float, bool])), + ivy.as_native_dtype( + draw(helpers.get_dtypes("valid", full=False, prune_function=False))[ + 0 + ] + ), + np_frontend.dtype( + draw(helpers.get_dtypes("valid", full=False, prune_function=False))[ + 0 + ] + ), + draw(st.sampled_from(list(np_frontend.numpy_scalar_to_dtype.keys()))), + draw(st.sampled_from(list(np_frontend.numpy_str_to_type_table.keys()))), + ] + ) ) 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_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 a3dd357e34cfe..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 @@ -161,17 +161,19 @@ def test_numpy_dot( @handle_frontend_test( fn_tree="numpy.linalg.matrix_and_vector_products.einsum", gt_fn_tree="numpy.einsum", - args=st.sampled_from([ - ( - "ii", - np.arange(25).reshape(5, 5), - ), - ( - "ii->i", - np.arange(25).reshape(5, 5), - ), - ("ij,j", np.arange(25).reshape(5, 5), np.arange(5)), - ]), + args=st.sampled_from( + [ + ( + "ii", + np.arange(25).reshape(5, 5), + ), + ( + "ii->i", + np.arange(25).reshape(5, 5), + ), + ("ij,j", np.arange(25).reshape(5, 5), np.arange(5)), + ] + ), dtype=helpers.get_dtypes("float", full=False), ) def test_numpy_einsum( @@ -322,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 07e9a06bfbcd2..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 @@ -27,9 +27,9 @@ def _get_inv_square_matrices(draw): ) shape, ind = draw( - st.sampled_from([ - (generated_shape, generated_ind), (handpicked_shape, handpicked_ind) - ]) + st.sampled_from( + [(generated_shape, generated_ind), (handpicked_shape, handpicked_ind)] + ) ) input_dtype = draw( @@ -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 6156d1fd3b612..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 @@ -13,18 +13,20 @@ @st.composite def _pad_helper(draw): mode = draw( - st.sampled_from([ - "constant", - "edge", - "linear_ramp", - "maximum", - "mean", - "median", - "minimum", - "reflect", - "symmetric", - "wrap", - ]) + st.sampled_from( + [ + "constant", + "edge", + "linear_ramp", + "maximum", + "mean", + "median", + "minimum", + "reflect", + "symmetric", + "wrap", + ] + ) ) if mode in ["median", "mean"]: dtypes = "float" 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_miscellaneous.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_miscellaneous.py index f596f3454031c..4fcafe638e4e7 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_miscellaneous.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_mathematical_functions/test_miscellaneous.py @@ -370,6 +370,49 @@ def test_numpy_gcd( ) +# gradient +@handle_frontend_test( + fn_tree="numpy.gradient", + dtype_input_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=1, + max_num_dims=3, + min_dim_size=2, + max_dim_size=4, + valid_axis=True, + force_int_axis=True, + ), + varargs=helpers.ints( + min_value=-3, + max_value=3, + ), +) +def test_numpy_gradient( + dtype_input_axis, + varargs, + frontend, + backend_fw, + test_flags, + fn_tree, + on_device, +): + input_dtype, x, axis = dtype_input_axis + test_flags.num_positional_args = 2 + kw = {} + kw["varargs"] = varargs + kw["axis"] = axis + 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, + f=x[0], + **kw, + ) + + # heaviside @handle_frontend_test( fn_tree="numpy.heaviside", 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 833da964cdfdd..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 @@ -3545,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( diff --git a/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_averages_and_variances.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_averages_and_variances.py index 74c69698e96e0..4405d2980ac80 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_averages_and_variances.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_averages_and_variances.py @@ -130,9 +130,9 @@ def test_numpy_average( on_device, ): try: - input_dtype, a, axis = dtype_and_a + input_dtype, a, axis, *_ = dtype_and_a - input_dtypes, xs, axiss = dtype_and_x + input_dtypes, xs, axiss, *_ = dtype_and_x if isinstance(axis, tuple): axis = axis[0] @@ -222,7 +222,7 @@ def test_numpy_mean( on_device, keep_dims, ): - input_dtypes, x, axis = dtype_and_x + input_dtypes, x, axis, _, _ = dtype_and_x where, input_dtypes, test_flags = np_frontend_helpers.handle_where_and_array_bools( where=where, input_dtype=input_dtypes, @@ -239,6 +239,7 @@ def test_numpy_mean( axis=axis, dtype=dtype[0], out=None, + atol=0.0005, keepdims=keep_dims, where=where, ) 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_numpy/test_statistics/test_order_statistics.py b/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_order_statistics.py index b9d641135e97d..4b8e29dc67752 100644 --- a/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_order_statistics.py +++ b/ivy_tests/test_ivy/test_frontends/test_numpy/test_statistics/test_order_statistics.py @@ -70,7 +70,7 @@ def test_numpy_ptp( fn_tree, keep_dims, ): - input_dtypes, values, axis = dtype_values_axis + input_dtypes, values, axis, _, _ = dtype_values_axis if isinstance(axis, tuple): axis = axis[0] 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 5f9ef493350e7..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 @@ -379,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..01b69b4b173c2 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(), ) @@ -423,6 +412,40 @@ def test_paddle_cond( ) +# cov +@handle_frontend_test( + fn_tree="paddle.linalg.cov", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("float"), + num_arrays=1, + max_num_dims=2, + ), + rowvar=st.booleans(), + ddof=st.booleans(), +) +def test_paddle_cov( + *, + dtype_and_x, + rowvar, + ddof, + frontend, + test_flags, + fn_tree, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + frontend=frontend, + test_flags=test_flags, + backend_to_test=backend_fw, + fn_tree=fn_tree, + x=x, + rowvar=rowvar, + ddof=ddof, + ) + + # Tests # # ----- # @@ -462,6 +485,8 @@ def test_paddle_cross( x=x, y=y, axis=axis, + atol=1e-4, + rtol=1e-4, ) @@ -569,7 +594,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 +644,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 +731,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 +852,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..435af95f08a43 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): @@ -241,6 +297,39 @@ def dtypes_x_reshape(draw): # ------------ # +@handle_frontend_test( + fn_tree="paddle.one_hot", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=["int64"], + min_value=0, + min_num_dims=1, + max_num_dims=5, + ), + num_classes=helpers.ints(min_value=1), +) +def test_one_hot( + *, + dtype_and_x, + num_classes, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, +): + input_dtype, x = dtype_and_x + helpers.test_frontend_function( + input_dtypes=input_dtype, + frontend=frontend, + test_flags=test_flags, + fn_tree=fn_tree, + on_device=on_device, + x=x[0], + num_classes=num_classes, + backend_to_test=backend_fw, + ) + + # abs @handle_frontend_test( fn_tree="paddle.abs", @@ -471,6 +560,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 c4b40e6a715d9..b48b5408536a5 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 @@ -838,39 +838,28 @@ def test_paddle_diagonal( # diff @handle_frontend_test( fn_tree="paddle.diff", - dtype_n_x_n_axis=helpers.dtype_values_axis( - available_dtypes=st.shared(helpers.get_dtypes("valid"), key="dtype"), + dtype_n_x_prepend_append=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=3, min_num_dims=1, valid_axis=True, force_int_axis=True, + shared_dtype=True, ), n=st.integers(min_value=1, max_value=1), - dtype_prepend=helpers.dtype_and_values( - available_dtypes=st.shared(helpers.get_dtypes("valid"), key="dtype"), - min_num_dims=1, - max_num_dims=1, - ), - dtype_append=helpers.dtype_and_values( - available_dtypes=st.shared(helpers.get_dtypes("valid"), key="dtype"), - min_num_dims=1, - max_num_dims=1, - ), ) def test_paddle_diff( *, - dtype_n_x_n_axis, + dtype_n_x_prepend_append, n, - dtype_prepend, - dtype_append, test_flags, frontend, backend_fw, fn_tree, on_device, ): - input_dtype, x, axis = dtype_n_x_n_axis - _, prepend = dtype_prepend - _, append = dtype_append + input_dtype, array, axis = dtype_n_x_prepend_append + x, prepend, append = array[0], array[1], array[2] helpers.test_frontend_function( input_dtypes=input_dtype, test_flags=test_flags, @@ -878,11 +867,11 @@ def test_paddle_diff( backend_to_test=backend_fw, fn_tree=fn_tree, on_device=on_device, - x=x[0], + x=x, n=n, axis=axis, - prepend=prepend[0], - append=append[0], + prepend=prepend, + append=append, ) @@ -1137,7 +1126,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( @@ -1165,7 +1154,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( @@ -1331,7 +1320,7 @@ def test_paddle_inner( 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: tuple([x, x])), + 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] @@ -1720,6 +1709,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", @@ -2111,7 +2133,7 @@ def test_paddle_pow( @handle_frontend_test( fn_tree="paddle.prod", dtype_and_x=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("valid"), min_axis=-1, max_axis=0, min_num_dims=1, @@ -2473,8 +2495,20 @@ def test_paddle_square( dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), ), - scale_a=st.floats(1e-5, 1e5), - scale_b=st.floats(1e-5, 1e5), + scale_a=st.floats( + min_value=-5, + max_value=5, + allow_nan=False, + allow_subnormal=False, + allow_infinity=False, + ), + scale_b=st.floats( + min_value=-5, + max_value=5, + allow_nan=False, + allow_subnormal=False, + allow_infinity=False, + ), ) def test_paddle_stanh( *, @@ -2700,7 +2734,7 @@ def test_paddle_trace( @handle_frontend_test( fn_tree="paddle.trunc", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float", "int"), + available_dtypes=helpers.get_dtypes("valid"), ), ) def test_paddle_trunc( @@ -2720,5 +2754,5 @@ def test_paddle_trunc( test_flags=test_flags, fn_tree=fn_tree, on_device=on_device, - x=x[0], + input=x[0], ) diff --git a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_activation.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_activation.py index a95ae21b3bf0f..64ce7c3c54abb 100644 --- a/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_activation.py +++ b/ivy_tests/test_ivy/test_frontends/test_paddle/test_nn/test_functional/test_activation.py @@ -737,6 +737,8 @@ def test_paddle_softplus( x=x[0], beta=beta, threshold=threshold, + rtol=1e-4, + atol=1e-4, ) 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 c70b27ae2e3c2..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 @@ -60,25 +60,27 @@ def _interp_args(draw, mode=None, mode_list=None): mode = draw(st.sampled_from(jax_modes)) else: mode = draw( - st.sampled_from([ - "linear", - "bilinear", - "trilinear", - "nearest", - "nearest-exact", - "area", - "tf_area", - "tf_bicubic", - "lanczos3", - "lanczos5", - "mitchellcubic", - "gaussian", - ]) + st.sampled_from( + [ + "linear", + "bilinear", + "trilinear", + "nearest", + "nearest-exact", + "area", + "tf_area", + "tf_bicubic", + "lanczos3", + "lanczos5", + "mitchellcubic", + "gaussian", + ] + ) ) 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 @@ -155,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_stat.py b/ivy_tests/test_ivy/test_frontends/test_paddle/test_stat.py index f8ccfc5b7ac2c..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, 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 32d7fc29f9c51..aa76cc3e282dc 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 @@ -160,6 +160,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): @@ -186,6 +219,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)) @@ -245,6 +288,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 @@ -269,18 +424,6 @@ def _reshape_helper(draw): return dtypes, x, reshape_shape -# 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 - - # expand helper function @st.composite def dtypes_x_shape(draw): @@ -351,6 +494,85 @@ def test_paddle___add__( ) +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="__float__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + max_num_dims=0, + ), +) +def test_paddle___float__( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + backend_fw, + frontend, + on_device, +): + 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_dtypes, + backend_to_test=backend_fw, + 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, + on_device=on_device, + ) + + +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + 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___floordiv__( + dtype_and_x, + 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[1], 0))) + 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, + atol_=1, + ) + + # __ge__ @handle_frontend_method( class_tree=CLASS_TREE, @@ -388,6 +610,40 @@ def test_paddle___ge__( ) +# __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])), +) +def test_paddle___getitem__( + dtype_x_index, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + input_dtype, x, index = dtype_x_index + helpers.test_frontend_method( + init_input_dtypes=[input_dtype[0]], + 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}, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # __gt__ @handle_frontend_method( class_tree=CLASS_TREE, @@ -425,6 +681,81 @@ def test_paddle___gt__( ) +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="__int__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + max_num_dims=0, + min_value=-1e15, + max_value=1e15, + ), +) +def test_paddle___int__( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + backend_fw, + frontend, + on_device, +): + 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_dtypes, + backend_to_test=backend_fw, + 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, + on_device=on_device, + ) + + +# invert +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="__invert__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + max_num_dims=0, + ), +) +def test_paddle___invert__( + dtype_and_x, + frontend_method_data, + init_flags, + method_flags, + backend_fw, + frontend, + on_device, +): + input_dtypes, xs = dtype_and_x + 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": xs[0], + }, + 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, + ) + + # __le__ @handle_frontend_method( class_tree=CLASS_TREE, @@ -462,90 +793,92 @@ def test_paddle___le__( ) -# __mul__ +# __len__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__mul__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True + method_name="__len__", + dtype_and_x=_array_and_shape( + min_num_dims=1, + max_num_dims=5, ), ) -def test_paddle___mul__( +def test_paddle___len__( dtype_and_x, + frontend, 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], + "value": x[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, ) -# __or__ +# long @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__or__", + method_name="__long__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("integer"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("integer"), + max_num_dims=0, + min_value=-1e15, + max_value=1e15, ), ) -def test_paddle___or__( +def test_paddle___long__( 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], - }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "y": x[1], + "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, ) -# __radd__ +# __lt__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__radd__", + method_name="__lt__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True ), ) -def test_paddle___radd__( +def test_paddle___lt__( dtype_and_x, frontend_method_data, init_flags, @@ -563,7 +896,7 @@ def test_paddle___radd__( }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={ - "x": x[1], + "y": x[1], }, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -573,17 +906,21 @@ def test_paddle___radd__( ) -# __setitem__ +# __mod__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__setitem__", - dtypes_x_index_val=helpers.dtype_array_query_val( + method_name="__mod__", + dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), - ).filter(lambda x: x[0][0] == x[0][-1] and _filter_query(x[-2])), + num_arrays=2, + shared_dtype=True, + min_value=0, + exclude_min=True, + ), ) -def test_paddle___setitem__( - dtypes_x_index_val, +def test_paddle___mod__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -591,13 +928,17 @@ def test_paddle___setitem__( on_device, backend_fw, ): - input_dtype, x, index, val = dtypes_x_index_val + 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={"data": x}, - method_input_dtypes=[*input_dtype[1:]], - method_all_as_kwargs_np={"item": index, "value": val}, + 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, @@ -606,16 +947,16 @@ def test_paddle___setitem__( ) -# __sub__ +# __mul__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__sub__", + method_name="__mul__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True + available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, shared_dtype=True ), ) -def test_paddle___sub__( +def test_paddle___mul__( dtype_and_x, frontend_method_data, init_flags, @@ -643,56 +984,60 @@ def test_paddle___sub__( ) +# __ne__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__float__", + method_name="__ne__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - max_num_dims=0, + available_dtypes=helpers.get_dtypes("float"), + num_arrays=2, + min_value=-1e04, + max_value=1e04, + allow_inf=False, ), ) -def test_paddle__float__( +def test_paddle___ne__( dtype_and_x, frontend_method_data, init_flags, method_flags, - backend_fw, frontend, on_device, + backend_fw, ): - input_dtypes, xs = dtype_and_x - # Numpy doesn't support complex to float conversion - assume(not np.issubdtype(input_dtypes[0], np.complexfloating)) + 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, - method_input_dtypes=input_dtypes, init_all_as_kwargs_np={ - "object": xs[0], + "data": 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, + frontend=frontend, on_device=on_device, ) +# __neg__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__floordiv__", + method_name="__neg__", 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", + min_value=-1e04, + max_value=1e04, + allow_inf=False, ), ) -def test_paddle__floordiv__( +def test_paddle___neg__( dtype_and_x, frontend_method_data, init_flags, @@ -702,7 +1047,6 @@ def test_paddle__floordiv__( backend_fw, ): input_dtype, x = dtype_and_x - assume(not np.any(np.isclose(x[1], 0))) helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -710,30 +1054,26 @@ def test_paddle__floordiv__( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": 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, ) -# __getitem__ +# __or__ @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="__or__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), num_arrays=2, shared_dtype=True + ), ) -def test_paddle__getitem__( - dtype_x_index, +def test_paddle___or__( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -741,13 +1081,17 @@ def test_paddle__getitem__( on_device, backend_fw, ): - 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={"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={ + "y": x[1], + }, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -756,65 +1100,68 @@ def test_paddle__getitem__( ) +# __radd__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__int__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("integer"), - max_num_dims=0, - min_value=-1e15, - max_value=1e15, + method_name="__radd__", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle__int__( +def test_paddle___radd__( dtype_and_x, frontend_method_data, init_flags, method_flags, - backend_fw, frontend, on_device, + backend_fw, ): - input_dtypes, xs = dtype_and_x - # Numpy doesn't support complex to int conversion - assume(not np.issubdtype(input_dtypes[0], np.complexfloating)) + 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, - method_input_dtypes=input_dtypes, init_all_as_kwargs_np={ - "object": xs[0], + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np={ + "x": 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, ) -# __len__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__len__", - dtype_and_x=_array_and_shape( - min_num_dims=1, - max_num_dims=5, + method_name="__rdiv__", + dtype_and_x=helpers.dtype_and_values( + 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__len__( +def test_paddle___rdiv__( dtype_and_x, frontend, frontend_method_data, init_flags, method_flags, - backend_fw, 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, @@ -822,7 +1169,9 @@ def test_paddle__len__( "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, @@ -831,11 +1180,11 @@ def test_paddle__len__( ) -# __ne__ +# __rmul__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__ne__", + method_name="__rmul__", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), num_arrays=2, @@ -844,7 +1193,7 @@ def test_paddle__len__( allow_inf=False, ), ) -def test_paddle__ne__( +def test_paddle___rmul__( dtype_and_x, frontend_method_data, init_flags, @@ -872,40 +1221,41 @@ def test_paddle__ne__( ) -# __neg__ +# __rsub__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__neg__", + method_name="__rsub__", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("float"), - min_value=-1e04, - max_value=1e04, - allow_inf=False, + available_dtypes=helpers.get_dtypes("numeric"), + num_arrays=2, + shared_dtype=True, ), ) -def test_paddle__neg__( +def test_paddle___rsub__( dtype_and_x, + frontend, 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], + "value": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, + method_all_as_kwargs_np={ + "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, ) @@ -913,7 +1263,7 @@ def test_paddle__neg__( @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__rdiv__", + method_name="__rtruediv__", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("numeric"), num_arrays=2, @@ -923,7 +1273,7 @@ def test_paddle__neg__( safety_factor_scale="log", ), ) -def test_paddle__rdiv__( +def test_paddle___rtruediv__( dtype_and_x, frontend, frontend_method_data, @@ -953,15 +1303,17 @@ def test_paddle__rdiv__( ) -# reshape +# __setitem__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="reshape", - dtype_x_shape=_reshape_helper(), + 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__reshape( - dtype_x_shape, +def test_paddle___setitem__( + dtypes_x_index_val, frontend_method_data, init_flags, method_flags, @@ -969,19 +1321,13 @@ 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, 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=shape, + 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, @@ -990,20 +1336,16 @@ def test_paddle__reshape( ) -# __rmul__ +# __sub__ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__rmul__", + method_name="__sub__", 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, + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle__rmul__( +def test_paddle___sub__( dtype_and_x, frontend_method_data, init_flags, @@ -1021,7 +1363,7 @@ def test_paddle__rmul__( }, method_input_dtypes=input_dtype, method_all_as_kwargs_np={ - "other": x[1], + "y": x[1], }, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -1031,45 +1373,6 @@ def test_paddle__rmul__( ) -# __rsub__ -@handle_frontend_method( - class_tree=CLASS_TREE, - init_tree="paddle.to_tensor", - method_name="__rsub__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - num_arrays=2, - shared_dtype=True, - ), -) -def test_paddle__rsub__( - 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={ - "x": x[1], - }, - frontend=frontend, - frontend_method_data=frontend_method_data, - init_flags=init_flags, - method_flags=method_flags, - on_device=on_device, - ) - - # __xor__ @handle_frontend_method( class_tree=CLASS_TREE, @@ -1081,7 +1384,7 @@ def test_paddle__rsub__( shared_dtype=True, ), ) -def test_paddle__xor__( +def test_paddle___xor__( dtype_and_x, frontend, frontend_method_data, @@ -2481,7 +2784,7 @@ def test_paddle_device( 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") ), ) @@ -3916,11 +4219,11 @@ def test_paddle_max( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", method_name="mean", - dtype_and_x=_statistical_dtype_values(function="mean"), + dtype_x_axis=_statistical_dtype_values(function="mean"), keepdim=st.booleans(), ) def test_paddle_mean( - dtype_and_x, + dtype_x_axis, keepdim, frontend, backend_fw, @@ -3929,7 +4232,7 @@ def test_paddle_mean( method_flags, on_device, ): - input_dtype, x, axis = dtype_and_x + input_dtype, x, axis, *_ = dtype_x_axis helpers.test_frontend_method( init_input_dtypes=input_dtype, init_all_as_kwargs_np={"data": x[0]}, @@ -4558,6 +4861,80 @@ def test_paddle_remainder_( ) +# reshape +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="reshape", + dtype_x_shape=_reshape_helper(), +) +def test_paddle_reshape( + dtype_x_shape, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + 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, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np=shape, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# reshape_ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="reshape_", + dtype_x_shape=_reshape_helper(), +) +def test_paddle_reshape_( + dtype_x_shape, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + 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, + init_all_as_kwargs_np={ + "data": x[0], + }, + method_input_dtypes=input_dtype, + method_all_as_kwargs_np=shape, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # rot90 @handle_frontend_method( class_tree=CLASS_TREE, @@ -5199,17 +5576,52 @@ def test_paddle_subtract_( ) -# t +# t +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="t", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + max_num_dims=2, + ), +) +def test_paddle_t( + 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, + ) + + +# tanh @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="t", + method_name="tanh", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), - max_num_dims=2, ), ) -def test_paddle_t( +def test_paddle_tanh( dtype_and_x, frontend_method_data, init_flags, @@ -5221,10 +5633,10 @@ def test_paddle_t( 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], }, - backend_to_test=backend_fw, method_input_dtypes=input_dtype, method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, @@ -5235,16 +5647,16 @@ def test_paddle_t( ) -# tanh +# tanh_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="tanh", + method_name="tanh_", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), ), ) -def test_paddle_tanh( +def test_paddle_tanh_( dtype_and_x, frontend_method_data, init_flags, @@ -5270,16 +5682,15 @@ def test_paddle_tanh( ) -# tanh_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="tanh_", + method_name="acos", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float"), ), ) -def test_paddle_tanh_( +def test_paddle_tensor_acos( dtype_and_x, frontend_method_data, init_flags, @@ -5305,46 +5716,37 @@ def test_paddle_tanh_( ) -# __div__ +# add @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", - method_name="__div__", + method_name="add", dtype_and_x=helpers.dtype_and_values( - 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", + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2, shared_dtype=True ), ) -def test_paddle_tensor__div__( +def test_paddle_tensor_add( 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={ - "value": x[0], + "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "y": x[1], - }, - 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, ) @@ -5401,6 +5803,57 @@ def test_paddle_tensor_chunk( ) +# cov +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + 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", + ), +) +def test_paddle_tensor_cov( + dtype_x1_corr_cov, + frontend_method_data, + init_flags, + method_flags, + frontend, + backend_fw, + on_device, +): + dtype, x, rowvar, ddof, fweights, aweights = dtype_x1_corr_cov + helpers.test_frontend_method( + init_input_dtypes=["float64", "int64", "float64"], + init_all_as_kwargs_np={ + "data": x, + }, + method_input_dtypes=["int64", "float64"], + backend_to_test=backend_fw, + method_all_as_kwargs_np={ + "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, + ) + + # expand @handle_frontend_method( class_tree=CLASS_TREE, @@ -5436,6 +5889,89 @@ def test_paddle_tensor_expand( ) +# flatten +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + 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_tensor_flatten( + dtype_value, + axes, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + 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], + }, + method_input_dtypes=input_dtype, + 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, + frontend=frontend, + on_device=on_device, + ) + + +# floor_mod +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="floor_mod", + dtypes_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + min_value=2, + shared_dtype=True, + ), +) +def test_paddle_tensor_floor_mod( + 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, + ) + + @handle_frontend_method( class_tree=CLASS_TREE, init_tree="paddle.to_tensor", @@ -5478,6 +6014,88 @@ def test_paddle_tensor_heaviside( ) +# matmul +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="matmul", + dtype_tensor1_tensor2=_get_dtype_and_multiplicative_matrices(), +) +def test_paddle_tensor_matmul( + dtype_tensor1_tensor2, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + dtype, tensor1, tensor2, transpose_x, transpose_y = dtype_tensor1_tensor2 + + helpers.test_frontend_method( + init_input_dtypes=dtype, + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": tensor1, + }, + method_input_dtypes=dtype, + method_all_as_kwargs_np={ + "y": tensor2, + "transpose_x": transpose_x, + "transpose_y": transpose_y, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# squeeze +@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"), + ), + axis=helpers.get_axis( + shape=st.shared(helpers.get_shape(), key="shape"), + allow_neg=True, + force_int=True, + ), +) +def test_paddle_tensor_squeeze( + dtype_value, + axis, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + 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], + }, + 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, + ) + + # tile @handle_frontend_method( class_tree=CLASS_TREE, @@ -5893,3 +6511,47 @@ def test_paddle_zero_( frontend=frontend, on_device=on_device, ) + + +# __div__ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="paddle.to_tensor", + method_name="__div__", + dtype_and_x=helpers.dtype_and_values( + 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_tensor__div__( + dtype_and_x, + frontend, + frontend_method_data, + init_flags, + method_flags, + 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={ + "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, + ) 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..c2a11908ddd5a 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,261 @@ def test_sklearn_accuracy_score( normalize=normalize, sample_weight=None, ) + + +@handle_frontend_test( + fn_tree="sklearn.metrics.f1_score", + arrays_and_dtypes=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + num_arrays=2, + min_value=0, + max_value=1, # F1 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_f1_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, + ) + + +@handle_frontend_test( + fn_tree="sklearn.metrics.hamming_loss", + arrays_and_dtypes=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + num_arrays=2, + min_value=0, + max_value=1, # Hamming loss 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_hamming_loss( + 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, + ) + + +@handle_frontend_test( + fn_tree="sklearn.metrics.precision_score", + arrays_and_dtypes=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + num_arrays=2, + min_value=0, + max_value=1, # Precision 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_precision_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, + ) + + +@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_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_func_wrapper.py b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_func_wrapper.py index 5d0290a5ea5cb..036a6fa1e8c54 100644 --- a/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_func_wrapper.py +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_func_wrapper.py @@ -22,18 +22,26 @@ @st.composite def _dtype_helper(draw): return draw( - st.sampled_from([ - draw(helpers.get_dtypes("valid", prune_function=False, full=False))[0], - ivy.as_native_dtype( - draw(helpers.get_dtypes("valid", prune_function=False, full=False))[0] - ), - draw(st.sampled_from(list(tf_frontend.tensorflow_enum_to_type.values()))), - draw(st.sampled_from(list(tf_frontend.tensorflow_enum_to_type.keys()))), - np_frontend.dtype( - draw(helpers.get_dtypes("valid", prune_function=False, full=False))[0] - ), - draw(st.sampled_from(list(np_frontend.numpy_scalar_to_dtype.keys()))), - ]) + st.sampled_from( + [ + draw(helpers.get_dtypes("valid", prune_function=False, full=False))[0], + ivy.as_native_dtype( + draw(helpers.get_dtypes("valid", prune_function=False, full=False))[ + 0 + ] + ), + draw( + st.sampled_from(list(tf_frontend.tensorflow_enum_to_type.values())) + ), + draw(st.sampled_from(list(tf_frontend.tensorflow_enum_to_type.keys()))), + np_frontend.dtype( + draw(helpers.get_dtypes("valid", prune_function=False, full=False))[ + 0 + ] + ), + draw(st.sampled_from(list(np_frontend.numpy_scalar_to_dtype.keys()))), + ] + ) ) 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 436047049f5e4..6dacb88aee03e 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 @@ -1,5 +1,6 @@ # global from hypothesis import strategies as st, assume +from hypothesis.extra.numpy import arrays import numpy as np from tensorflow import errors as tf_errors @@ -228,11 +229,13 @@ def _multiple_shape_helper(draw): @st.composite def _pad_helper(draw): mode = draw( - st.sampled_from([ - "CONSTANT", - "REFLECT", - "SYMMETRIC", - ]) + st.sampled_from( + [ + "CONSTANT", + "REFLECT", + "SYMMETRIC", + ] + ) ) dtype, input, shape = draw( helpers.dtype_and_values( @@ -283,19 +286,21 @@ def _sequence_mask_helper(draw): 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", - ]) + st.sampled_from( + [ + "float16", + "uint8", + "complex128", + "bool", + "float64", + "int8", + "int16", + "complex64", + "float32", + "int32", + "int64", + ] + ) ) return in_dtype, lens, max_len, dtype @@ -363,6 +368,96 @@ def _strided_slice_helper(draw): return dtype, x, np.array(begin), np.array(end), np.array(strides), masks +@st.composite +def _values_and_ndindices( + draw, + *, + indices_dtypes=helpers.get_dtypes("valid"), + array_dtypes=helpers.get_dtypes("numeric"), + allow_inf=False, + x_min_value=None, + x_max_value=None, + min_num_dims=2, + max_num_dims=5, + min_dim_size=1, + max_dim_size=10, +): + # Generate the dtype and values for x + x_dtype, x, x_shape = draw( + helpers.dtype_and_values( + allow_inf=allow_inf, + ret_shape=True, + min_value=x_min_value, + max_value=x_max_value, + min_num_dims=min_num_dims, + max_num_dims=max_num_dims, + min_dim_size=min_dim_size, + max_dim_size=max_dim_size, + ) + ) + x_dtype = x_dtype[0] if isinstance(x_dtype, list) else x_dtype + x = x[0] if isinstance(x, list) else x + + # Determine the number of index dimensions + indices_dims = draw( + helpers.ints( + min_value=1, + max_value=len(x_shape), + ) + ) + + dtype_str = draw(st.sampled_from(indices_dtypes)) + if dtype_str == "int16": + dtype = np.int16 + elif dtype_str == "int32": + dtype = np.int32 + else: + dtype = np.int64 + + # Generate the shape of the output tensor + output_shape = draw( + arrays( + dtype=dtype, + shape=(indices_dims,), + elements=st.integers(min_value=1, max_value=max_dim_size), + ) + ) + + # Ensure output_shape is at least as large as x_shape up to indices_dims + for i in range(indices_dims): + output_shape[i] = max(output_shape[i], x_shape[i]) + + # Generate the number of indices + num_indices = draw(helpers.ints(min_value=1, max_value=10)) + + # Generate the indices + indices = [] + for _ in range(num_indices): + index = [ + draw(st.integers(min_value=0, max_value=output_shape[j] - 1)) + for j in range(indices_dims) + ] + indices.append(index) + indices = np.array(indices, dtype=dtype) + + # Generate the dtype and values for updates + updates_shape = list(indices.shape[:-1]) + list(output_shape[indices.shape[-1] :]) + updates_dtype, updates = draw( + helpers.dtype_and_values( + available_dtypes=array_dtypes, + allow_inf=allow_inf, + shape=updates_shape, + shared_dtype=True, + ) + ) + updates_dtype = ( + updates_dtype[0] if isinstance(updates_dtype, list) else updates_dtype + ) + updates = updates[0] if isinstance(updates, list) else updates + + return [x_dtype, indices.dtype, updates_dtype], x, indices, updates, output_shape + + @st.composite def _x_cast_dtype_shape(draw): x_dtype = draw(helpers.get_dtypes("valid", full=False)) @@ -725,11 +820,13 @@ def test_tensorflow_convert_to_tensor( # einsum @handle_frontend_test( fn_tree="tensorflow.einsum", - eq_n_op_n_shp=st.sampled_from([ - ("ii", (np.arange(25).reshape(5, 5),), ()), - ("ii->i", (np.arange(25).reshape(5, 5),), (5,)), - ("ij,j", (np.arange(25).reshape(5, 5), np.arange(5)), (5,)), - ]), + eq_n_op_n_shp=st.sampled_from( + [ + ("ii", (np.arange(25).reshape(5, 5),), ()), + ("ii->i", (np.arange(25).reshape(5, 5),), (5,)), + ("ij,j", (np.arange(25).reshape(5, 5), np.arange(5)), (5,)), + ] + ), dtype=helpers.get_dtypes("float", full=False), ) def test_tensorflow_einsum( @@ -1474,7 +1571,7 @@ def test_tensorflow_rank( frontend, test_flags, ): - dtype, x, _ = dtype_and_x + dtype, x, *_ = dtype_and_x helpers.test_frontend_function( input_dtypes=dtype, frontend=frontend, @@ -1693,6 +1790,41 @@ def _test_fn(a, x): ) +# scatter_nd +@handle_frontend_test( + fn_tree="tensorflow.scatter_nd", + x=_values_and_ndindices( + indices_dtypes=["int32", "int64"], + array_dtypes=helpers.get_dtypes("numeric"), + x_min_value=0, + x_max_value=0, + min_num_dims=2, + allow_inf=False, + ), +) +def test_tensorflow_scatter_nd( + *, + x, + test_flags, + backend_fw, + fn_tree, + frontend, + on_device, +): + (_, ind_dtype, update_dtype), _, ind, updates, shape = x + helpers.test_frontend_function( + input_dtypes=[update_dtype, ind_dtype], + frontend=frontend, + test_flags=test_flags, + on_device=on_device, + backend_to_test=backend_fw, + fn_tree=fn_tree, + indices=ind, + updates=updates, + shape=shape, + ) + + # searchsorted @handle_frontend_test( fn_tree="tensorflow.searchsorted", @@ -2533,9 +2665,9 @@ def _test_body_fn(x): input=helpers.get_shape( allow_none=False, min_num_dims=0, - max_num_dims=10, + max_num_dims=9, min_dim_size=0, - max_dim_size=10, + max_dim_size=9, ), dtype=helpers.get_dtypes("valid", full=False), ) @@ -2564,7 +2696,7 @@ def test_tensorflow_zeros( @handle_frontend_test( fn_tree="tensorflow.zeros_like", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric") + available_dtypes=helpers.get_dtypes("numeric"), ), dtype=helpers.get_dtypes("numeric", full=False), test_with_out=st.just(False), 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 7d3fca6e829d7..b04289ee565a0 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 @@ -13,6 +13,18 @@ except ImportError: tf = SimpleNamespace() +# Activation functions for testing +ACTIVATION_FUNCTIONS = [ + "gelu", + "leaky_relu", + "log_softmax", + "relu", + "sigmoid", + "silu", + "softmax", + "softplus", +] + # Helper function for deserialize. def get_callable_functions( @@ -39,6 +51,7 @@ def simple_test_two_function( atol_: float = 1e-06, ivy_submodules: list = [], framework_submodules: list = [], + backend: str, ): ivy.set_backend(frontend) fn_ivy = ivy.functional.frontends.__dict__[frontend] @@ -58,14 +71,15 @@ def simple_test_two_function( ret_ivy = ivy.array(ret_ivy, dtype=dtype_data) ret = ivy.array(ret, dtype=dtype_data) - ret_np_flat = helpers.flatten_and_to_np(ret=ret) - frontend_ret_np_flat = helpers.flatten_and_to_np(ret=ret_ivy) + ret_np_flat = helpers.flatten_and_to_np(backend=backend, ret=ret) + frontend_ret_np_flat = helpers.flatten_and_to_np(backend=backend, ret=ret_ivy) helpers.value_test( ret_np_flat=ret_np_flat, ret_np_from_gt_flat=frontend_ret_np_flat, rtol=rtol_, atol=atol_, + backend=backend, ground_truth_backend=frontend, ) ivy.previous_backend() @@ -75,23 +89,13 @@ def simple_test_two_function( @handle_frontend_test( fn_tree="tensorflow.keras.activations.deserialize", fn_name=st.sampled_from(get_callable_functions("keras.activations")).filter( - lambda x: not x[0].isupper() - and x - not in [ - "deserialize", - "get", - "keras_export", - "serialize", - "deserialize_keras_object", - "serialize_keras_object", - "get_globals", - ] + lambda x: not x[0].isupper() and x in ACTIVATION_FUNCTIONS ), dtype_and_data=helpers.dtype_and_values( 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( @@ -100,6 +104,7 @@ def test_tensorflow_deserialize( fn_name, fn_tree, frontend, + backend_fw, ): dtype_data, data = dtype_and_data simple_test_two_function( @@ -112,6 +117,7 @@ def test_tensorflow_deserialize( atol_=1e-01, ivy_submodules=["keras", "activations"], framework_submodules=["keras", "activations"], + backend=backend_fw, ) @@ -190,31 +196,22 @@ def test_tensorflow_gelu( @handle_frontend_test( fn_tree="tensorflow.keras.activations.get", fn_name=st.sampled_from(get_callable_functions("keras.activations")).filter( - lambda x: not x[0].isupper() - and x - not in [ - "deserialize", - "get", - "keras_export", - "serialize", - "deserialize_keras_object", - "serialize_keras_object", - "get_globals", - ] + lambda x: not x[0].isupper() and x in ACTIVATION_FUNCTIONS ), dtype_and_data=helpers.dtype_and_values( 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): +def test_tensorflow_get(fn_name, dtype_and_data, backend_fw): dtype_data, data = dtype_and_data simple_test_two_function( fn_name=fn_name, x=data[0], frontend="tensorflow", + backend=backend_fw, fn_str="get", dtype_data=dtype_data[0], rtol_=1e-01, @@ -363,7 +360,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..c65aedde00025 --- /dev/null +++ b/ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_backend.py @@ -0,0 +1,415 @@ +# 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, + ) + + +# sum +@handle_frontend_test( + fn_tree="tensorflow.keras.backend.sum", + 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_sum( + *, + 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, + ) 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..55bcad00d5271 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", @@ -669,6 +702,8 @@ def test_tensorflow_count_nonzero( on_device, ): input_dtype, x, axis = dtype_x_axis + if backend_fw == "paddle": + assume(not np.any(np.less_equal(x, 1e-08))) helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -1633,7 +1668,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 +1700,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, ), @@ -1696,7 +1731,7 @@ def test_tensorflow_logical_not( @handle_frontend_test( fn_tree="tensorflow.math.logical_or", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("bool"), + available_dtypes=(ivy.bool,), num_arrays=2, shared_dtype=True, ), @@ -1728,7 +1763,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 +1795,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, ), @@ -2169,6 +2204,8 @@ def test_tensorflow_reciprocal_no_nan( on_device, ): input_dtype, x = dtype_and_x + if backend_fw == "paddle": + assume(not np.any(np.less_equal(x, 1e-08))) helpers.test_frontend_function( input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -2184,7 +2221,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 +2250,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), ) @@ -2339,6 +2376,8 @@ def test_tensorflow_reduce_max( fn_tree="tensorflow.math.reduce_mean", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("float"), + min_value=-1e30, + max_value=1e30, ), test_with_out=st.just(False), ) @@ -2399,6 +2438,9 @@ def test_tensorflow_reduce_min( fn_tree="tensorflow.math.reduce_prod", dtype_and_x=helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("numeric"), + large_abs_safety_factor=24, + small_abs_safety_factor=24, + safety_factor_scale="log", ), test_with_out=st.just(False), ) @@ -2650,6 +2692,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 a92976f53aecc..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 @@ -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"), @@ -683,6 +687,8 @@ def test_tensorflow_avg_pool2d( ksize=ksize, strides=strides, padding=padding, + rtol=1e-2, + atol=1e-2, ) @@ -926,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, 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 66acd2020de79..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, @@ -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_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..f66853869c8e4 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 @@ -6,7 +6,6 @@ # 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_core.test_linalg import _matrix_rank_helper from ivy_tests.test_ivy.helpers.hypothesis_helpers.general_helpers import ( matrix_is_stable, ) @@ -524,7 +523,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 @@ -541,10 +540,9 @@ def test_torch_cholesky( backend_fw, ): dtype, x = dtype_and_x - x = x[0] - x = ( - np.matmul(x.T, x) + np.identity(x.shape[0]) * 1e-3 - ) # make symmetric positive-definite + x = np.asarray(x[0], dtype=dtype[0]) + x = np.matmul(np.conjugate(x.T), x) + np.identity(x.shape[0], dtype=dtype[0]) + # make symmetric positive-definite helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, @@ -652,6 +650,7 @@ def test_torch_logdet( backend_fw, ): dtype, x = dtype_and_x + assume(matrix_is_stable(x)) helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, @@ -691,37 +690,6 @@ def test_torch_matmul( ) -# matrix_rank -@handle_frontend_test( - fn_tree="torch.linalg.matrix_rank", - # aliases=["torch.matrix_rank",], deprecated since 1.9. uncomment with multi-version - # testing pipeline - dtype_x_hermitian_atol_rtol=_matrix_rank_helper(), -) -def test_torch_matrix_rank( - dtype_x_hermitian_atol_rtol, - on_device, - fn_tree, - frontend, - test_flags, - backend_fw, -): - dtype, x, hermitian, atol, rtol = dtype_x_hermitian_atol_rtol - assume(matrix_is_stable(x, cond_limit=10)) - 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, - A=x, - atol=atol, - rtol=rtol, - hermitian=hermitian, - ) - - # mm @handle_frontend_test( fn_tree="torch.mm", 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..829ed11e63e62 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 @@ -143,6 +143,7 @@ def test_torch_eq( num_arrays=2, allow_inf=False, shared_dtype=True, + abs_smallest_val=1e-07, ), ) def test_torch_equal( @@ -368,7 +369,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 +659,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 +689,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_indexing_slicing_joining_mutating_ops.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_indexing_slicing_joining_mutating_ops.py index f08400ec8e6c3..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,8 +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.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, ) @@ -337,7 +337,7 @@ def _dtypes_input_mask(draw): @st.composite def _where_helper(draw): - shape_1, shape_2 = draw(hh.two_broadcastable_shapes()) + shape_1, shape_2 = draw(two_broadcastable_shapes()) dtype_x1, x1 = draw( helpers.dtype_and_values( available_dtypes=helpers.get_dtypes("valid"), @@ -1356,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, @@ -1368,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, @@ -1376,7 +1379,7 @@ def test_torch_stack( fn_tree=fn_tree, on_device=on_device, tensors=value, - dim=dim, + **dim_arg, ) 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 40e88dbcda2cc..3af1cc7f64318 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 @@ -68,7 +68,7 @@ def _get_axis_and_p(draw): 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"], @@ -288,8 +319,8 @@ def test_torch_cholesky( ): dtype, x = dtype_and_x x = np.asarray(x[0], dtype=dtype[0]) - x = np.matmul(x.T, x) + np.identity(x.shape[0]) # make symmetric positive-definite - + x = np.matmul(np.conjugate(x.T), x) + np.identity(x.shape[0], dtype=dtype[0]) + # make symmetric positive-definite helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, @@ -305,7 +336,7 @@ def test_torch_cholesky( @handle_frontend_test( fn_tree="torch.linalg.cholesky_ex", - dtype_and_x=_get_dtype_and_matrix(square=True, batch=True), + dtype_and_x=_get_dtype_and_matrix(square=True), upper=st.booleans(), ) def test_torch_cholesky_ex( @@ -319,8 +350,9 @@ def test_torch_cholesky_ex( backend_fw, ): dtype, x = dtype_and_x - x = np.matmul(x.T, x) + np.identity(x.shape[0]) # make symmetric positive-definite - + x = np.asarray(x[0], dtype=dtype[0]) + x = np.matmul(np.conjugate(x.T), x) + np.identity(x.shape[0], dtype=dtype[0]) + # make symmetric positive-definite helpers.test_frontend_function( input_dtypes=dtype, backend_to_test=backend_fw, @@ -424,6 +456,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 +533,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 +542,7 @@ def test_torch_eig( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) @@ -511,6 +587,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 +618,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 +658,7 @@ def test_torch_eigvals( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) @@ -688,7 +767,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 +777,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( @@ -773,28 +904,35 @@ def test_torch_matrix_exp( 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=st.sampled_from((None, "16", "32", "64")), ) 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 is not None: + # torch backend does not allow down-casting. + if input_dtype[0] == "complex128": + dtypes = input_dtype[0] + else: + dtypes = input_dtype[0][0:-2] + max([input_dtype[0][-2:], dtypes]) helpers.test_frontend_function( input_dtypes=input_dtype, @@ -809,7 +947,7 @@ def test_torch_matrix_norm( ord=ord, dim=axis, keepdim=keepdim, - dtype=dtype[0], + dtype=dtypes, ) @@ -867,9 +1005,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 +1140,7 @@ def test_torch_qr( rtol=1e-2, atol=1e-2, ground_truth_backend=frontend, + backend=backend_fw, ) ivy.previous_backend() @@ -1149,6 +1290,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..b120a5a37d486 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,53 @@ 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, + ), + infer_dim=st.booleans(), +) +def test_torch_unflatten( + *, + dtype_and_values, + on_device, + fn_tree, + frontend, + test_flags, + backend_fw, + shape, + axis, + infer_dim, +): + dtype, x = dtype_and_values + sizes = sizes_(shape, axis) + if infer_dim and len(sizes) > 1: + sizes = list(sizes) + sizes[0] = -1 + sizes = tuple(sizes) + 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 f8cd1dfcbae57..6c69aa5b0dddd 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 @@ -227,9 +227,6 @@ def _x_and_filters(draw, dim: int = 2, transpose: bool = False, max_dilation=3): ) 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 - if dim != 2: - output_padding[i] = min(padding[i], output_padding[i]) m = min(fstrides[i], fdilations[i]) output_padding[i] = min(output_padding[i], m - 1) if draw(st.booleans()): @@ -364,9 +361,9 @@ def test_torch_conv3d( @handle_frontend_test( fn_tree="torch.nn.functional.conv_transpose1d", - dtype_vals=_x_and_filters(dim=1, transpose=True, max_dilation=1), + dtype_vals=_x_and_filters(dim=1, transpose=True), ) -def test_torch_conv_tranpose1d( +def test_torch_conv_transpose1d( *, dtype_vals, on_device, @@ -376,6 +373,13 @@ def test_torch_conv_tranpose1d( backend_fw, ): dtype, vals, weight, bias, dilations, strides, padding, output_pad, fc = dtype_vals + assume( + 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, @@ -399,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, @@ -409,6 +413,13 @@ def test_torch_conv_tranpose2d( backend_fw, ): dtype, vals, weight, bias, dilations, strides, padding, output_pad, fc = dtype_vals + assume( + 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, @@ -430,9 +441,9 @@ def test_torch_conv_tranpose2d( @handle_frontend_test( fn_tree="torch.nn.functional.conv_transpose3d", - dtype_vals=_x_and_filters(dim=3, transpose=True, max_dilation=1), + dtype_vals=_x_and_filters(dim=3, transpose=True), ) -def test_torch_conv_tranpose3d( +def test_torch_conv_transpose3d( *, dtype_vals, on_device, @@ -442,6 +453,13 @@ def test_torch_conv_tranpose3d( backend_fw, ): dtype, vals, weight, bias, dilations, strides, padding, output_pad, fc = dtype_vals + assume( + 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, @@ -505,6 +523,9 @@ def test_torch_unfold( backend_fw, ): dtype, vals, kernel_shape, dilations, strides, padding = dtype_vals + # TODO add bfloat16 to unsupported dtypes of the tested function + if backend_fw == "paddle": + assume("bfloat16" not in dtype[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_layer_functions.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_layer_functions.py index 1395d00bb080b..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 @@ -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_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 953e6865a11c7..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), ) @@ -649,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, @@ -660,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 7abe0b623de58..665e54d9156c5 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 @@ -118,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, @@ -160,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", @@ -436,10 +479,12 @@ def test_torch_max_pool1d( ), test_with_out=st.just(False), ceil_mode=st.booleans(), + return_indices=st.booleans(), ) def test_torch_max_pool2d( x_k_s_p, ceil_mode, + return_indices, *, test_flags, frontend, @@ -463,6 +508,7 @@ def test_torch_max_pool2d( padding=padding, dilation=dilation, ceil_mode=ceil_mode, + return_indices=return_indices, ) @@ -480,10 +526,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, @@ -494,6 +542,8 @@ def test_torch_max_pool3d( 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 5d9de4b6aff10..74ff174309488 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 @@ -69,7 +69,7 @@ def _pad_generator(draw, shape, mode): pad = pad + draw( st.tuples( st.integers(min_value=0, max_value=max(0, max_pad_value)), - st.integers(min_value=0, max_value=max(0, max_pad_value)), + st.integers(min_value=-3, max_value=max(0, max_pad_value)), ) ) return pad @@ -78,12 +78,14 @@ def _pad_generator(draw, shape, mode): @st.composite def _pad_helper(draw): mode = draw( - st.sampled_from([ - "constant", - "reflect", - "replicate", - "circular", - ]) + st.sampled_from( + [ + "constant", + "reflect", + "replicate", + "circular", + ] + ) ) min_v = 1 max_v = 5 @@ -97,14 +99,14 @@ def _pad_helper(draw): ret_shape=True, min_num_dims=min_v, max_num_dims=max_v, - min_dim_size=2, + min_dim_size=5, min_value=-1e05, max_value=1e05, ) ) 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 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 0e7744ac41a41..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 @@ -9,7 +9,6 @@ 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 --- # @@ -1182,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"), ), @@ -1212,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( @@ -2325,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 9d3f52db9a672..5f9316a06fba5 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 @@ -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, @@ -486,7 +489,7 @@ def test_torch_mean( on_device=on_device, input=x[0], dim=axis, - keepdim=keepdims, + keepdims=keepdims, dtype=dtypes[0], atol=1e-2, ) @@ -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_tensor.py b/ivy_tests/test_ivy/test_frontends/test_torch/test_tensor.py index a4b88c6137f96..1b4c8080695b6 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, @@ -220,6 +221,34 @@ def _fill_value_and_size( return dtype, [array, size, fill_value] +# float_power_helper +@st.composite +def _float_power_helper(draw, *, available_dtypes=None): + if available_dtypes is None: + available_dtypes = helpers.get_dtypes("numeric") + dtype1, x1 = draw( + helpers.dtype_and_values( + available_dtypes=available_dtypes, + small_abs_safety_factor=16, + large_abs_safety_factor=16, + safety_factor_scale="log", + ) + ) + dtype2 = draw(helpers.get_dtypes("numeric")) + if ivy.is_int_dtype(dtype2[0]): + min_value = 0 + else: + min_value = -10 + dtype2, x2 = draw( + helpers.dtype_and_values( + min_value=min_value, + max_value=10, + dtype=dtype2, + ) + ) + return (dtype1[0], dtype2[0]), (x1[0], x2[0]) + + @st.composite def _get_clamp_inputs(draw): shape = draw( @@ -331,6 +360,24 @@ def _masked_fill_helper(draw): return dtypes[0], xs[0], cond, fill_value +@st.composite +def _masked_scatter_helper(draw): + shape = draw(helpers.get_shape(min_num_dims=1, min_dim_size=1)) + dtypes, xs = draw( + helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + num_arrays=2, + shape=shape, + shared_dtype=True, + large_abs_safety_factor=16, + small_abs_safety_factor=16, + safety_factor_scale="log", + ) + ) + mask = draw(helpers.array_values(dtype="bool", shape=shape)) + return dtypes[0], xs[0], mask, xs[1] + + @st.composite def _repeat_helper(draw): shape = draw( @@ -346,16 +393,25 @@ def _repeat_helper(draw): ) ) - repeats = draw(st.lists(st.integers(min_value=1, max_value=5), min_size=len(shape))) + MAX_NUMPY_DIMS = 32 + repeats = draw( + st.lists( + st.integers(min_value=1, max_value=5), + min_size=len(shape), + max_size=MAX_NUMPY_DIMS, + ) + ) + assume(np.prod(repeats) * np.prod(shape) <= 2**28) return input_dtype, x, repeats @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 +471,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 +557,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", @@ -721,28 +796,63 @@ def test_torch___gt__( backend_fw, ): input_dtype, x = dtype_and_x - try: - 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, - ) - except RuntimeError as e: - if "overflow" in e: - assume(False) - else: - raise + 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( + 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, + ) # __invert__ @@ -1177,7 +1287,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, @@ -1409,37 +1519,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), @@ -4697,10 +4776,9 @@ def test_torch_cholesky( backend_fw, ): input_dtype, x = dtype_and_x - x = x[0] + x = np.asarray(x[0], dtype=input_dtype[0]) + x = np.matmul(np.conjugate(x.T), x) + np.identity(x.shape[0], dtype=input_dtype[0]) # make symmetric positive-definite - x = np.matmul(x.swapaxes(-1, -2), x) + np.identity(x.shape[-1]) * 1e-3 - helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -4870,6 +4948,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, @@ -5820,7 +5933,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") ), ) @@ -6374,16 +6487,19 @@ def test_torch_erf_( ) -# exp +# erfinv_ tests @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", - method_name="exp", + method_name="erfinv_", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + available_dtypes=helpers.get_dtypes("float"), + min_value=-1, + max_value=1, + abs_smallest_val=1e-05, ), ) -def test_torch_exp( +def test_torch_erfinv( dtype_and_x, frontend_method_data, init_flags, @@ -6409,17 +6525,20 @@ def test_torch_exp( ) -# exp_ +# erfinv_ tests @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", - method_name="exp_", + method_name="erfinv_", dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), + 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_exp_( +def test_torch_erfinv_( dtype_and_x, frontend_method_data, init_flags, @@ -6445,16 +6564,17 @@ def test_torch_exp_( ) +# exp @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", - method_name="expand", - dtype_x_shape=_expand_helper(), - unpack_shape=st.booleans(), + method_name="exp", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), + ), ) -def test_torch_expand( - dtype_x_shape, - unpack_shape, +def test_torch_exp( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -6462,18 +6582,7 @@ def test_torch_expand( on_device, backend_fw, ): - input_dtype, x, shape = dtype_x_shape - if unpack_shape: - method_flags.num_positional_args = len(shape) + 1 - size = {} - i = 0 - for x_ in shape: - size[f"x{i}"] = x_ - i += 1 - else: - size = { - "size": shape, - } + input_dtype, x = dtype_and_x helpers.test_frontend_method( init_input_dtypes=input_dtype, backend_to_test=backend_fw, @@ -6481,7 +6590,7 @@ def test_torch_expand( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np=size, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -6490,17 +6599,18 @@ def test_torch_expand( ) -# expand_as +# exp_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", - method_name="expand_as", - dtype_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("valid"), num_arrays=2 + method_name="exp_", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("numeric"), ), + test_inplace=st.just(True), ) -def test_torch_expand_as( - dtype_x, +def test_torch_exp_( + dtype_and_x, frontend_method_data, init_flags, method_flags, @@ -6508,7 +6618,7 @@ def test_torch_expand_as( 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, @@ -6516,9 +6626,7 @@ def test_torch_expand_as( "data": x[0], }, method_input_dtypes=input_dtype, - method_all_as_kwargs_np={ - "other": x[1], - }, + method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -6527,16 +6635,105 @@ def test_torch_expand_as( ) -# expm1 @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", - method_name="expm1", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - ), + method_name="expand", + dtype_x_shape=_expand_helper(), + unpack_shape=st.booleans(), ) -def test_torch_expm1( +def test_torch_expand( + dtype_x_shape, + unpack_shape, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + 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 = {} + i = 0 + for x_ in shape: + size[f"x{i}"] = x_ + i += 1 + else: + size = { + "size": shape, + } + 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=size, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# expand_as +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="expand_as", + dtype_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), num_arrays=2 + ), +) +def test_torch_expand_as( + dtype_x, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + 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": 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, + ) + + +# expm1 +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="expm1", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("valid"), + ), +) +def test_torch_expm1( dtype_and_x, frontend_method_data, init_flags, @@ -6638,6 +6835,49 @@ def test_torch_fill_( ) +# fill_diagonal_ +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="fill_diagonal_", + dtype_x_axis=helpers.dtype_values_axis( + available_dtypes=helpers.get_dtypes("float"), + min_num_dims=2, + min_dim_size=2, + max_num_dims=2, + ), + val=helpers.floats(min_value=-10, max_value=10), + wrap=st.booleans(), +) +def test_torch_fill_diagonal_( + dtype_x_axis, + wrap, + val, + frontend, + frontend_method_data, + init_flags, + method_flags, + 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={ + "fill_value": val, + "wrap": wrap, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # fix @handle_frontend_method( class_tree=CLASS_TREE, @@ -7088,6 +7328,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", @@ -7654,6 +7932,104 @@ def test_torch_index_fill( ) +# todo: remove dtype specifications +@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(), +) +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, @@ -7695,6 +8071,41 @@ def test_torch_index_select( ) +# float_power +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="float_power", + dtype_and_x=_float_power_helper(), +) +def test_torch_instance_float_power( + dtype_and_x, + frontend, + frontend_method_data, + init_flags, + method_flags, + on_device, + backend_fw, +): + input_dtype, x = dtype_and_x + # Making sure zero to the power of negative doesn't occur + assume(not np.any(np.isclose(x[0], 0))) + 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={ + "exponent": x[1], + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + # int @handle_frontend_method( class_tree=CLASS_TREE, @@ -7903,6 +8314,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, @@ -8568,6 +9017,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, @@ -8794,6 +9288,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, @@ -8820,10 +9352,117 @@ def test_torch_logit( init_input_dtypes=input_dtype, backend_to_test=backend_fw, init_all_as_kwargs_np={ - "data": x[0], + "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, + ) + + +# long +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="long", + dtype_and_x=helpers.dtype_and_values( + available_dtypes=helpers.get_dtypes("integer"), + ), +) +def test_torch_long( + 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, + ) + + +# masked_fill +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="masked_fill", + x_mask_val=_masked_fill_helper(), +) +def test_torch_masked_fill( + x_mask_val, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + dtype, x, mask, val = x_mask_val + helpers.test_frontend_method( + init_input_dtypes=[dtype], + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x, + }, + method_input_dtypes=["bool", dtype], + method_all_as_kwargs_np={ + "mask": mask, + "value": val, + }, + frontend_method_data=frontend_method_data, + init_flags=init_flags, + method_flags=method_flags, + frontend=frontend, + on_device=on_device, + ) + + +# masked_scatter +@handle_frontend_method( + class_tree=CLASS_TREE, + init_tree="torch.tensor", + method_name="masked_scatter", + dtype_x_mask_val=_masked_scatter_helper(), +) +def test_torch_masked_scatter( + dtype_x_mask_val, + frontend_method_data, + init_flags, + method_flags, + frontend, + on_device, + backend_fw, +): + dtype, x, mask, val = dtype_x_mask_val + helpers.test_frontend_method( + init_input_dtypes=[dtype], + backend_to_test=backend_fw, + init_all_as_kwargs_np={ + "data": x, + }, + method_input_dtypes=["bool", dtype], + method_all_as_kwargs_np={ + "mask": mask, + "source": val, }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -8832,17 +9471,15 @@ def test_torch_logit( ) -# long +# masked_scatter_ @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", - method_name="long", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("integer"), - ), + method_name="masked_scatter_", + dtype_x_mask_val=_masked_scatter_helper(), ) -def test_torch_long( - dtype_and_x, +def test_torch_masked_scatter_( + dtype_x_mask_val, frontend_method_data, init_flags, method_flags, @@ -8850,15 +9487,18 @@ def test_torch_long( on_device, backend_fw, ): - input_dtype, x = dtype_and_x + dtype, x, mask, val = dtype_x_mask_val 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": x, + }, + method_input_dtypes=["bool", dtype], + method_all_as_kwargs_np={ + "mask": mask, + "source": val, }, - method_input_dtypes=input_dtype, - method_all_as_kwargs_np={}, frontend_method_data=frontend_method_data, init_flags=init_flags, method_flags=method_flags, @@ -8867,14 +9507,14 @@ def test_torch_long( ) -# masked_fill +# masked_select @handle_frontend_method( class_tree=CLASS_TREE, init_tree="torch.tensor", - method_name="masked_fill", + method_name="masked_select", x_mask_val=_masked_fill_helper(), ) -def test_torch_masked_fill( +def test_torch_masked_select( x_mask_val, frontend_method_data, init_flags, @@ -8883,7 +9523,7 @@ def test_torch_masked_fill( on_device, backend_fw, ): - dtype, x, mask, val = x_mask_val + dtype, x, mask, _ = x_mask_val helpers.test_frontend_method( init_input_dtypes=[dtype], backend_to_test=backend_fw, @@ -8893,7 +9533,6 @@ def test_torch_masked_fill( method_input_dtypes=["bool", dtype], method_all_as_kwargs_np={ "mask": mask, - "value": val, }, frontend_method_data=frontend_method_data, init_flags=init_flags, @@ -9862,6 +10501,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, @@ -9953,14 +10625,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, @@ -9969,6 +10639,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, @@ -10042,14 +10713,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, @@ -10058,6 +10727,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, @@ -10203,8 +10873,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 @@ -10329,9 +10999,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, ) @@ -10905,6 +11576,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, } @@ -11240,9 +11917,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, @@ -12429,7 +13104,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(), @@ -12753,6 +13428,160 @@ def test_torch_tensor_corrcoef( ) +# 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, + ) + + +# 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, @@ -13462,6 +14291,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, 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 c2686e8d00b35..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,14 +44,16 @@ 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, - # nested_values, - ]) + st.sampled_from( + [ + x, + x_list, + # sh, + # nested_values, + ] + ) ) return x_dtype, x, dtype @@ -183,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( *, @@ -846,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 8145e909d85ad..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 @@ -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 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 89071dec7917e..0699c8f2786f5 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") @@ -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], @@ -1941,6 +1980,7 @@ def test_tanh(*, dtype_and_x, complex_mode, test_flags, backend_fw, fn_name, on_ ), rand_either=_either_x_dx(), test_gradients=st.just(False), + ground_truth_backend="numpy", ) def test_trapz( dtype_values_axis, rand_either, test_flags, backend_fw, fn_name, on_device 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 edf425cb782c1..52c06db92ef55 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 @@ -408,10 +412,12 @@ def test_arg_info(): @given( - x_n_value=st.sampled_from([ - [ivy.value_is_nan, ["x", "include_infs"]], - [ivy.clip_matrix_norm, ["x", "max_norm", "p", "out"]], - ]) + x_n_value=st.sampled_from( + [ + [ivy.value_is_nan, ["x", "include_infs"]], + [ivy.clip_matrix_norm, ["x", "max_norm", "p", "out"]], + ] + ) ) def test_arg_names(x_n_value): x, value = x_n_value @@ -627,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 @@ -710,15 +716,17 @@ def test_default(x, default_val, test_flags, backend_fw): and (ivy.array([x[1][0]], dtype="float32").shape[3] % 2 == 0) and (x[0][0] not in ["float16", "bfloat16"]) ), - pattern_and_axes_lengths=st.sampled_from([ - ("b h w c -> b h w c", {}), - ("b h w c -> (b h) w c", {}), - ("b h w c -> b c h w", {}), - ("b h w c -> h (b w) c", {}), - ("b h w c -> b (c h w)", {}), - ("b (h1 h) (w1 w) c -> (b h1 w1) h w c", {"h1": 2, "w1": 2}), - ("b (h h1) (w w1) c -> b h w (c h1 w1)", {"h1": 2, "w1": 2}), - ]), + pattern_and_axes_lengths=st.sampled_from( + [ + ("b h w c -> b h w c", {}), + ("b h w c -> (b h) w c", {}), + ("b h w c -> b c h w", {}), + ("b h w c -> h (b w) c", {}), + ("b h w c -> b (c h w)", {}), + ("b (h1 h) (w1 w) c -> (b h1 w1) h w c", {"h1": 2, "w1": 2}), + ("b (h h1) (w w1) c -> b h w (c h1 w1)", {"h1": 2, "w1": 2}), + ] + ), ) def test_einops_rearrange( dtype_x, pattern_and_axes_lengths, test_flags, backend_fw, fn_name, on_device @@ -754,9 +762,11 @@ def test_einops_rearrange( and (ivy.array([x[1][0]], dtype="float32").shape[3] % 2 == 0) and (x[0][0] not in ["float16", "bfloat16"]) ), - pattern_and_axes_lengths=st.sampled_from([ - ("b c (h1 h2) (w1 w2) -> b c h1 w1", {"h2": 2, "w2": 2}), - ]), + pattern_and_axes_lengths=st.sampled_from( + [ + ("b c (h1 h2) (w1 w2) -> b c h1 w1", {"h2": 2, "w2": 2}), + ] + ), floattypes=helpers.get_dtypes("float"), reduction=st.sampled_from(["min", "max", "sum", "mean", "prod"]), ) @@ -803,13 +813,15 @@ def test_einops_reduce( max_num_dims=2, min_dim_size=2, ), - pattern_and_axes_lengths=st.sampled_from([ - ("h w -> h w repeat", {"repeat": 2}), - ("h w -> (repeat h) w", {"repeat": 2}), - ("h w -> h (repeat w)", {"repeat": 2}), - ("h w -> (h h2) (w w2)", {"h2": 2, "w2": 2}), - ("h w -> w h", {}), - ]), + pattern_and_axes_lengths=st.sampled_from( + [ + ("h w -> h w repeat", {"repeat": 2}), + ("h w -> (repeat h) w", {"repeat": 2}), + ("h w -> h (repeat w)", {"repeat": 2}), + ("h w -> (h h2) (w w2)", {"h2": 2, "w2": 2}), + ("h w -> w h", {}), + ] + ), ) def test_einops_repeat( *, dtype_x, pattern_and_axes_lengths, test_flags, backend_fw, fn_name, on_device @@ -845,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) @@ -999,6 +1011,9 @@ def test_function_unsupported_devices(func, backend_fw): max_num_dims=5, min_dim_size=1, max_dim_size=10, + large_abs_safety_factor=1.5, + small_abs_safety_factor=1.5, + safety_factor_scale="log", ), ) def test_gather(params_indices_others, test_flags, backend_fw, fn_name, on_device): @@ -1013,6 +1028,9 @@ def test_gather(params_indices_others, test_flags, backend_fw, fn_name, on_devic params=params, indices=indices, axis=axis, + atol_=1e-3, + rtol_=1e-3, + tolerance_dict={"bfloat16": 1e-1}, batch_dims=batch_dims, ) @@ -1062,6 +1080,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, @@ -1200,7 +1227,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 @@ -1281,7 +1308,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 @@ -1321,7 +1348,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 @@ -1635,6 +1662,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, @@ -1714,6 +1755,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", 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..c5095e5a917ef 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(), ) @@ -641,26 +644,36 @@ def test_matmul(*, x, y, test_flags, backend_fw, fn_name, on_device): # matrix_norm @handle_test( fn_tree="functional.ivy.matrix_norm", - # ground_truth_backend="numpy", dtype_value_axis=helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("float"), + available_dtypes=helpers.get_dtypes("valid"), min_num_dims=2, valid_axis=True, min_axes_size=2, max_axes_size=2, + max_value=1e4, + min_value=-1e4, + abs_smallest_val=1e-4, force_tuple_axis=True, allow_neg_axes=False, ), kd=st.booleans(), ord=st.sampled_from((-2, -1, 1, 2, -float("inf"), float("inf"), "fro", "nuc")), + dtypes=st.sampled_from((None, "16", "32", "64")), ) def test_matrix_norm( - *, dtype_value_axis, kd, ord, test_flags, backend_fw, fn_name, on_device + *, dtype_value_axis, kd, ord, dtypes, test_flags, backend_fw, fn_name, on_device ): - dtype, x, axis = dtype_value_axis + input_dtype, x, axis = dtype_value_axis + if dtypes is not None: + # torch backend does not allow down-casting. + if input_dtype[0] == "complex128": + dtypes = input_dtype[0] + else: + dtypes = input_dtype[0][0:-2] + max([input_dtype[0][-2:], dtypes]) + assume(matrix_is_stable(x[0], cond_limit=10)) helpers.test_function( - input_dtypes=dtype, + input_dtypes=input_dtype, test_flags=test_flags, backend_to_test=backend_fw, fn_name=fn_name, @@ -670,6 +683,7 @@ def test_matrix_norm( x=x[0], axis=axis, keepdims=kd, + dtype=dtypes, ord=ord, ) @@ -681,7 +695,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 54fceaf059e28..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 @@ -45,32 +45,36 @@ def test_fomaml_step_overlapping_vars( # create variables if batched: - variables = ivy_backend.Container({ - "latent": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[0.0]], device=on_device), - num_tasks, - axis=0, - ) - ), - "weight": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[1.0]], device=on_device), - num_tasks, - axis=0, - ) - ), - }) + variables = ivy_backend.Container( + { + "latent": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[0.0]], device=on_device), + num_tasks, + axis=0, + ) + ), + "weight": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[1.0]], device=on_device), + num_tasks, + axis=0, + ) + ), + } + ) else: - variables = ivy_backend.Container({ - "latent": variable_fn(ivy_backend.array([0.0], device=on_device)), - "weight": variable_fn(ivy_backend.array([1.0], device=on_device)), - }) + variables = ivy_backend.Container( + { + "latent": variable_fn(ivy_backend.array([0.0], device=on_device)), + "weight": variable_fn(ivy_backend.array([1.0], device=on_device)), + } + ) # batch - batch = ivy_backend.Container({ - "x": ivy_backend.arange(1, num_tasks + 1, dtype="float32") - }) + batch = ivy_backend.Container( + {"x": ivy_backend.arange(1, num_tasks + 1, dtype="float32")} + ) # inner cost function def inner_cost_fn(batch_in, v): @@ -102,14 +106,16 @@ def outer_cost_fn(batch_in, v): # true gradient all_outer_grads = [] for sub_batch in batch_np.cont_unstack_conts(0, True, num_tasks): - all_outer_grads.append([ - ( - -i * inner_learning_rate * weight_np * sub_batch["x"][0] ** 2 - - sub_batch["x"][0] * latent_np - ) - * (-1 if with_outer_cost_fn else 1) - for i in range(inner_grad_steps + 1) - ]) + all_outer_grads.append( + [ + ( + -i * inner_learning_rate * weight_np * sub_batch["x"][0] ** 2 + - sub_batch["x"][0] * latent_np + ) + * (-1 if with_outer_cost_fn else 1) + for i in range(inner_grad_steps + 1) + ] + ) if average_across_steps: true_weight_grad = ( sum(sum(og) / len(og) for og in all_outer_grads) / num_tasks @@ -118,9 +124,9 @@ def outer_cost_fn(batch_in, v): true_weight_grad = sum(og[-1] for og in all_outer_grads) / num_tasks # true latent gradient - true_latent_grad = np.array([ - (-1 - (num_tasks - 1) / 2) * (-1 if with_outer_cost_fn else 1) - ]) + true_latent_grad = np.array( + [(-1 - (num_tasks - 1) / 2) * (-1 if with_outer_cost_fn else 1)] + ) # true cost true_cost_dict = { @@ -212,24 +218,26 @@ def test_fomaml_step_shared_vars( # create variable if batched: - variables = ivy_backend.Container({ - "latent": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[1.0]], device=on_device), - num_tasks, - axis=0, + variables = ivy_backend.Container( + { + "latent": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[1.0]], device=on_device), + num_tasks, + axis=0, + ) ) - ) - }) + } + ) else: - variables = ivy_backend.Container({ - "latent": variable_fn(ivy_backend.array([1.0], device=on_device)) - }) + variables = ivy_backend.Container( + {"latent": variable_fn(ivy_backend.array([1.0], device=on_device))} + ) # batch - batch = ivy_backend.Container({ - "x": ivy_backend.arange(1, num_tasks + 1, dtype="float32") - }) + batch = ivy_backend.Container( + {"x": ivy_backend.arange(1, num_tasks + 1, dtype="float32")} + ) # inner cost function def inner_cost_fn(batch_in, v): @@ -401,32 +409,36 @@ def test_fomaml_step_unique_vars( # create variables if batched: - variables = ivy_backend.Container({ - "latent": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[0.0]], device=on_device), - num_tasks, - axis=0, - ) - ), - "weight": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[1.0]], device=on_device), - num_tasks, - axis=0, - ) - ), - }) + variables = ivy_backend.Container( + { + "latent": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[0.0]], device=on_device), + num_tasks, + axis=0, + ) + ), + "weight": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[1.0]], device=on_device), + num_tasks, + axis=0, + ) + ), + } + ) else: - variables = ivy_backend.Container({ - "latent": variable_fn(ivy_backend.array([0.0], device=on_device)), - "weight": variable_fn(ivy_backend.array([1.0], device=on_device)), - }) + variables = ivy_backend.Container( + { + "latent": variable_fn(ivy_backend.array([0.0], device=on_device)), + "weight": variable_fn(ivy_backend.array([1.0], device=on_device)), + } + ) # batch - batch = ivy_backend.Container({ - "x": ivy_backend.arange(1, num_tasks + 1, dtype="float32") - }) + batch = ivy_backend.Container( + {"x": ivy_backend.arange(1, num_tasks + 1, dtype="float32")} + ) # inner cost function def inner_cost_fn(batch_in, v): @@ -458,14 +470,16 @@ def outer_cost_fn(batch_in, v): # true gradient all_outer_grads = [] for sub_batch in batch_np.cont_unstack_conts(0, True, num_tasks): - all_outer_grads.append([ - ( - -i * inner_learning_rate * weight_np * sub_batch["x"][0] ** 2 - - sub_batch["x"][0] * latent_np - ) - * (-1 if with_outer_cost_fn else 1) - for i in range(inner_grad_steps + 1) - ]) + all_outer_grads.append( + [ + ( + -i * inner_learning_rate * weight_np * sub_batch["x"][0] ** 2 + - sub_batch["x"][0] * latent_np + ) + * (-1 if with_outer_cost_fn else 1) + for i in range(inner_grad_steps + 1) + ] + ) if average_across_steps: true_weight_grad = ( sum(sum(og) / len(og) for og in all_outer_grads) / num_tasks @@ -559,32 +573,36 @@ def test_maml_step_overlapping_vars( # create variables if batched: - variables = ivy_backend.Container({ - "latent": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[0.0]], device=on_device), - num_tasks, - axis=0, - ) - ), - "weight": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[1.0]], device=on_device), - num_tasks, - axis=0, - ) - ), - }) + variables = ivy_backend.Container( + { + "latent": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[0.0]], device=on_device), + num_tasks, + axis=0, + ) + ), + "weight": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[1.0]], device=on_device), + num_tasks, + axis=0, + ) + ), + } + ) else: - variables = ivy_backend.Container({ - "latent": variable_fn(ivy_backend.array([0.0], device=on_device)), - "weight": variable_fn(ivy_backend.array([1.0], device=on_device)), - }) + variables = ivy_backend.Container( + { + "latent": variable_fn(ivy_backend.array([0.0], device=on_device)), + "weight": variable_fn(ivy_backend.array([1.0], device=on_device)), + } + ) # batch - batch = ivy_backend.Container({ - "x": ivy_backend.arange(1, num_tasks + 1, dtype="float32") - }) + batch = ivy_backend.Container( + {"x": ivy_backend.arange(1, num_tasks + 1, dtype="float32")} + ) # inner cost function def inner_cost_fn(batch_in, v): @@ -616,14 +634,20 @@ def outer_cost_fn(batch_in, v): # true weight gradient all_outer_grads = [] for sub_batch in batch_np.cont_unstack_conts(0, True, num_tasks): - all_outer_grads.append([ - ( - -2 * i * inner_learning_rate * weight_np * sub_batch["x"][0] ** 2 - - sub_batch["x"][0] * latent_np - ) - * (-1 if with_outer_cost_fn else 1) - for i in range(inner_grad_steps + 1) - ]) + all_outer_grads.append( + [ + ( + -2 + * i + * inner_learning_rate + * weight_np + * sub_batch["x"][0] ** 2 + - sub_batch["x"][0] * latent_np + ) + * (-1 if with_outer_cost_fn else 1) + for i in range(inner_grad_steps + 1) + ] + ) if average_across_steps: true_weight_grad = ( sum(sum(og) / len(og) for og in all_outer_grads) / num_tasks @@ -632,9 +656,9 @@ def outer_cost_fn(batch_in, v): true_weight_grad = sum(og[-1] for og in all_outer_grads) / num_tasks # true latent gradient - true_latent_grad = np.array([ - (-1 - (num_tasks - 1) / 2) * (-1 if with_outer_cost_fn else 1) - ]) + true_latent_grad = np.array( + [(-1 - (num_tasks - 1) / 2) * (-1 if with_outer_cost_fn else 1)] + ) # true cost true_cost_dict = { @@ -724,24 +748,26 @@ def test_maml_step_shared_vars( # create variable if batched: - variables = ivy_backend.Container({ - "latent": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[1.0]], device=on_device), - num_tasks, - axis=0, + variables = ivy_backend.Container( + { + "latent": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[1.0]], device=on_device), + num_tasks, + axis=0, + ) ) - ) - }) + } + ) else: - variables = ivy_backend.Container({ - "latent": variable_fn(ivy_backend.array([1.0], device=on_device)) - }) + variables = ivy_backend.Container( + {"latent": variable_fn(ivy_backend.array([1.0], device=on_device))} + ) # batch - batch = ivy_backend.Container({ - "x": ivy_backend.arange(1, num_tasks + 1, dtype="float32") - }) + batch = ivy_backend.Container( + {"x": ivy_backend.arange(1, num_tasks + 1, dtype="float32")} + ) # inner cost function def inner_cost_fn(batch_in, v): @@ -954,32 +980,36 @@ def test_maml_step_unique_vars( # create variables if batched: - variables = ivy_backend.Container({ - "latent": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[0.0]], device=on_device), - num_tasks, - axis=0, - ) - ), - "weight": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[1.0]], device=on_device), - num_tasks, - axis=0, - ) - ), - }) + variables = ivy_backend.Container( + { + "latent": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[0.0]], device=on_device), + num_tasks, + axis=0, + ) + ), + "weight": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[1.0]], device=on_device), + num_tasks, + axis=0, + ) + ), + } + ) else: - variables = ivy_backend.Container({ - "latent": variable_fn(ivy_backend.array([0.0], device=on_device)), - "weight": variable_fn(ivy_backend.array([1.0], device=on_device)), - }) + variables = ivy_backend.Container( + { + "latent": variable_fn(ivy_backend.array([0.0], device=on_device)), + "weight": variable_fn(ivy_backend.array([1.0], device=on_device)), + } + ) # batch - batch = ivy_backend.Container({ - "x": ivy_backend.arange(1, num_tasks + 1, dtype="float32") - }) + batch = ivy_backend.Container( + {"x": ivy_backend.arange(1, num_tasks + 1, dtype="float32")} + ) # inner cost function def inner_cost_fn(batch_in, v): @@ -1011,14 +1041,20 @@ def outer_cost_fn(batch_in, v): # true gradient all_outer_grads = [] for sub_batch in batch_np.cont_unstack_conts(0, True, num_tasks): - all_outer_grads.append([ - ( - -2 * i * inner_learning_rate * weight_np * sub_batch["x"][0] ** 2 - - sub_batch["x"][0] * latent_np - ) - * (-1 if with_outer_cost_fn else 1) - for i in range(inner_grad_steps + 1) - ]) + all_outer_grads.append( + [ + ( + -2 + * i + * inner_learning_rate + * weight_np + * sub_batch["x"][0] ** 2 + - sub_batch["x"][0] * latent_np + ) + * (-1 if with_outer_cost_fn else 1) + for i in range(inner_grad_steps + 1) + ] + ) if average_across_steps: true_outer_grad = ( sum(sum(og) / len(og) for og in all_outer_grads) / num_tasks @@ -1107,24 +1143,26 @@ def test_reptile_step( # create variable if batched: - variables = ivy_backend.Container({ - "latent": variable_fn( - ivy_backend.repeat( - ivy_backend.array([[1.0]], device=on_device), - num_tasks, - axis=0, + variables = ivy_backend.Container( + { + "latent": variable_fn( + ivy_backend.repeat( + ivy_backend.array([[1.0]], device=on_device), + num_tasks, + axis=0, + ) ) - ) - }) + } + ) else: - variables = ivy_backend.Container({ - "latent": variable_fn(ivy_backend.array([1.0], device=on_device)) - }) + variables = ivy_backend.Container( + {"latent": variable_fn(ivy_backend.array([1.0], device=on_device))} + ) # batch - batch = ivy_backend.Container({ - "x": ivy_backend.arange(1, num_tasks + 1, dtype="float32") - }) + batch = ivy_backend.Container( + {"x": ivy_backend.arange(1, num_tasks + 1, dtype="float32")} + ) # inner cost function def inner_cost_fn(batch_in, v): 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 87b230fdf9649..2de2f8ee6e322 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 @@ -45,7 +45,7 @@ def _statistical_dtype_values(draw, *, function, min_value=None, max_value=None) small_abs_safety_factor = 24 dtype, values, axis = draw( helpers.dtype_values_axis( - available_dtypes=helpers.get_dtypes("valid"), + available_dtypes=helpers.get_dtypes("float_and_complex"), large_abs_safety_factor=large_abs_safety_factor, small_abs_safety_factor=small_abs_safety_factor, safety_factor_scale="log", @@ -63,10 +63,10 @@ def _statistical_dtype_values(draw, *, function, min_value=None, max_value=None) shape = values[0].shape size = values[0].size max_correction = np.min(shape) - if "complex" in dtype[0]: - # TODO skip complex median test until added ? - # because it is not supported in tensorflow (ground truth backend) - dtype = ["float32"] + # TODO skip complex median test until added or add decorator + # for unsupported dtypes? + # because it is not supported in tensorflow (ground truth backend) + assume("complex" not in dtype[0]) if any(ele in function for ele in ["std", "var"]): if size == 1: correction = 0 @@ -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, @@ -236,9 +252,12 @@ def test_max(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_devi fn_tree="functional.ivy.mean", dtype_and_x=_statistical_dtype_values(function="mean"), keep_dims=st.booleans(), + dtypes=helpers.get_dtypes("float", none=True, full=False), ) -def test_mean(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_device): - input_dtype, x, axis = dtype_and_x +def test_mean( + *, dtype_and_x, keep_dims, dtypes, test_flags, backend_fw, fn_name, on_device +): + input_dtype, x, axis, dtype3, where = dtype_and_x helpers.test_function( input_dtypes=input_dtype, test_flags=test_flags, @@ -251,6 +270,7 @@ def test_mean(*, dtype_and_x, keep_dims, test_flags, backend_fw, fn_name, on_dev x=x[0], axis=axis, keepdims=keep_dims, + dtype=dtypes[0], ) @@ -259,11 +279,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 +295,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], ) 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 151cc3fcb344d..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 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_gradients.py b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_gradients.py index b5226c371a127..f34b3513a8290 100644 --- a/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_gradients.py +++ b/ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_gradients.py @@ -13,22 +13,26 @@ def _get_primals_and_tangents(x_, dtype, ivy_backend, primals_cont, tangents_cont): if primals_cont: - primals = ivy_backend.Container({ - "l": { - "a": ivy_backend.array(x_[0][0], dtype=dtype), - "b": ivy_backend.array(x_[0][1], dtype=dtype), + primals = ivy_backend.Container( + { + "l": { + "a": ivy_backend.array(x_[0][0], dtype=dtype), + "b": ivy_backend.array(x_[0][1], dtype=dtype), + } } - }) + ) else: primals = ivy_backend.array(x_[0], dtype=dtype) if tangents_cont: - tangents = ivy_backend.Container({ - "l": { - "a": ivy_backend.array([t[0] for t in x_[1]], dtype=dtype), - "b": ivy_backend.array([t[0] for t in x_[1]], dtype=dtype), + tangents = ivy_backend.Container( + { + "l": { + "a": ivy_backend.array([t[0] for t in x_[1]], dtype=dtype), + "b": ivy_backend.array([t[0] for t in x_[1]], dtype=dtype), + } } - }) + ) else: if primals_cont: tangents = ivy_backend.array([t[0] for t in x_[1]], dtype=dtype) 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 fe2f805d4759b..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, ) @@ -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(), 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 1fe495ad058aa..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, @@ -205,19 +206,21 @@ def _matricize_data(draw): @st.composite def _pad_helper(draw): mode = draw( - st.sampled_from([ - "constant", - "dilated", - "edge", - "linear_ramp", - "maximum", - "mean", - "median", - "minimum", - "reflect", - "symmetric", - "wrap", - ]) + st.sampled_from( + [ + "constant", + "dilated", + "edge", + "linear_ramp", + "maximum", + "mean", + "median", + "minimum", + "reflect", + "symmetric", + "wrap", + ] + ) ) if mode in ["median", "minimum", "maximum", "linear_ramp"]: dtypes = "float" @@ -1468,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 5a79ef33ad3cf..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"]), ) 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 ba074d564ba52..8289adef6238d 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 --- # @@ -65,20 +65,22 @@ def _interp_args(draw, mode=None, mode_list=None): mode = draw(st.sampled_from(jax_modes)) else: mode = draw( - st.sampled_from([ - "linear", - "bilinear", - "trilinear", - "nearest", - "nearest-exact", - "area", - "tf_area", - "tf_bicubic", - "lanczos3", - "lanczos5", - "mitchellcubic", - "gaussian", - ]) + st.sampled_from( + [ + "linear", + "bilinear", + "trilinear", + "nearest", + "nearest-exact", + "area", + "tf_area", + "tf_bicubic", + "lanczos3", + "lanczos5", + "mitchellcubic", + "gaussian", + ] + ) ) elif mode_list: mode = draw(st.sampled_from(mode_list)) @@ -152,6 +154,93 @@ def _interp_args(draw, mode=None, mode_list=None): 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)) @@ -368,6 +457,45 @@ def _x_and_ifftn(draw): return dtype, x, s, axes, norm +@st.composite +def _x_and_ifftn_jax(draw): + min_fft_points = 2 + dtype = draw(helpers.get_dtypes("complex")) + x_dim = draw( + helpers.get_shape( + min_dim_size=2, max_dim_size=100, min_num_dims=1, max_num_dims=4 + ) + ) + x = draw( + helpers.array_values( + dtype=dtype[0], + shape=tuple(x_dim), + min_value=-1e-10, + max_value=1e10, + ) + ) + axes = draw( + st.lists( + st.integers(0, len(x_dim) - 1), + min_size=1, + max_size=min(len(x_dim), 3), + unique=True, + ) + ) + norm = draw(st.sampled_from(["forward", "ortho", "backward"])) + + # Shape for s can be larger, smaller or equal to the size of the input + # along the axes specified by axes. + # Here, we're generating a list of integers corresponding to each axis in axes. + s = draw( + st.lists( + st.integers(min_fft_points, 256), min_size=len(axes), max_size=len(axes) + ) + ) + + return dtype, x, s, axes, norm + + @st.composite def _x_and_rfft(draw): min_fft_points = 2 @@ -500,7 +628,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, ), @@ -511,11 +639,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( @@ -526,6 +655,7 @@ def test_adaptive_avg_pool2d( fn_name=fn_name, input=x[0], output_size=output_size, + data_format=data_format, ) @@ -566,6 +696,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), @@ -1367,6 +1533,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_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 7da0237633a0e..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 --- # @@ -83,6 +83,157 @@ def _general_transpose_helper(draw): 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()) @@ -465,7 +616,6 @@ def _x_and_filters( depthwise=False, general=False, bias=False, - filter_format=None, ): if not isinstance(dim, int): dim = draw(dim) @@ -480,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) @@ -551,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 @@ -596,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 = ( @@ -610,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( @@ -624,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, @@ -651,6 +800,7 @@ def _x_and_filters_and_transpose( pad, output_shape, fc, + filter_format, bias, ) = all_args else: @@ -925,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", ) @@ -986,6 +1135,7 @@ 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 # tensorflow does not work with dilations > 1 on cpu @@ -1003,6 +1153,7 @@ def test_conv1d_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, bias=bias, @@ -1015,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", ) @@ -1075,6 +1225,7 @@ 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(isinstance(pad, str) or backend_fw in ["torch", "tensorflow"]) @@ -1092,6 +1243,7 @@ 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, bias=bias, @@ -1104,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", ) @@ -1164,6 +1315,7 @@ 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) @@ -1180,6 +1332,7 @@ 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, bias=bias, @@ -1194,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 @@ -1254,6 +1406,7 @@ def test_conv_general_transpose( pad, output_shape, fc, + filter_format, bias, ) = dim_x_f_d_df assume(isinstance(pad, str) or backend_fw in ["torch", "tensorflow"]) @@ -1271,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, @@ -1388,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 1c334ef0ebb92..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( + ["!=", ">", "<", ">=", "<=", "*", "/", "%", "==", "&", "@", "**", "/"], ), - 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_backend_utils/test_backend_handler.py b/ivy_tests/test_ivy/test_misc/test_backend_utils/test_backend_handler.py index ac26cf7ba3906..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,7 +88,7 @@ def test_current_backend(backend, array_type): @pytest.mark.parametrize( - ["middle_backend", "end_backend"], + ("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): @@ -107,10 +107,12 @@ def test_dynamic_backend_all_combos(middle_backend, end_backend): # 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])), - }) + 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 a.dynamic_backend = True diff --git a/ivy_tests/test_ivy/test_misc/test_container.py b/ivy_tests/test_ivy/test_misc/test_container.py index 4e0621b0ef31f..f9641e5e98cbe 100644 --- a/ivy_tests/test_ivy/test_misc/test_container.py +++ b/ivy_tests/test_ivy/test_misc/test_container.py @@ -19,9 +19,9 @@ def test_container_all_false(on_device): assert not Container({"a": False, "b": {"c": [1], "d": 0}}).cont_all_false() # noinspection PyBroadException try: - assert Container({ - "a": ivy.array([1], device=on_device), "b": {"c": [1], "d": True} - }).cont_all_false(assert_is_bool=True) + assert Container( + {"a": ivy.array([1], device=on_device), "b": {"c": [1], "d": True}} + ).cont_all_false(assert_is_bool=True) error_raised = False except IvyException: error_raised = True @@ -42,17 +42,17 @@ def test_container_all_key_chains(include_empty, on_device): def test_container_all_true(on_device): - assert not Container({ - "a": ivy.array([1], device=on_device), "b": {"c": [], "d": True} - }).cont_all_true() - assert Container({ - "a": ivy.array([1], device=on_device), "b": {"c": [1], "d": True} - }).cont_all_true() + assert not Container( + {"a": ivy.array([1], device=on_device), "b": {"c": [], "d": True}} + ).cont_all_true() + assert Container( + {"a": ivy.array([1], device=on_device), "b": {"c": [1], "d": True}} + ).cont_all_true() # noinspection PyBroadException try: - assert Container({ - "a": ivy.array([1], device=on_device), "b": {"c": [1], "d": True} - }).cont_all_true(assert_is_bool=True) + assert Container( + {"a": ivy.array([1], device=on_device), "b": {"c": [1], "d": True}} + ).cont_all_true(assert_is_bool=True) error_raised = False except IvyException: error_raised = True @@ -103,10 +103,12 @@ def test_container_assert_contains(on_device): error_caught = True assert error_caught # sub-structure - sub_struc = Container({ - "c": ivy.array([3.0], device=on_device), - "d": ivy.array([4.0], device=on_device), - }) + sub_struc = Container( + { + "c": ivy.array([3.0], device=on_device), + "d": ivy.array([4.0], device=on_device), + } + ) try: not container.cont_assert_contains_sub_container(sub_struc) error_caught = False @@ -136,13 +138,15 @@ def test_container_assert_identical(on_device): arr3 = ivy.array([3], device=on_device) container0 = Container({"a": arr1, "b": {"c": arr2, "d": arr3}}) container1 = Container({"a": arr1, "b": {"c": arr2, "d": arr3}}) - container2 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) + container2 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) container3 = Container({"b": {"d": arr3}}) container4 = Container({"d": arr3}) @@ -177,36 +181,44 @@ def test_container_assert_identical(on_device): def test_container_assert_identical_structure(on_device): # without key_chains specification - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container1 = Container({ - "a": ivy.array([3], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([5], device=on_device), - }, - }) - container2 = Container({ - "a": ivy.array([3], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([5], device=on_device), + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container1 = Container( + { + "a": ivy.array([3], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([5], device=on_device), + }, + } + ) + container2 = Container( + { + "a": ivy.array([3], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([5], device=on_device), + "e": ivy.array([6], device=on_device), + }, + } + ) + container3 = Container( + { + "a": ivy.array([3], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([5], device=on_device), + }, "e": ivy.array([6], device=on_device), - }, - }) - container3 = Container({ - "a": ivy.array([3], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([5], device=on_device), - }, - "e": ivy.array([6], device=on_device), - }) + } + ) container4 = Container({"b": {"d": ivy.array([4], device=on_device)}}) container5 = Container({"d": ivy.array([4], device=on_device)}) @@ -217,9 +229,9 @@ def test_container_assert_identical_structure(on_device): # without identical try: - ivy.Container.cont_assert_identical_structure([ - container0, container1, container2, container3 - ]) + ivy.Container.cont_assert_identical_structure( + [container0, container1, container2, container3] + ) error_caught = False except IvyException: error_caught = True @@ -314,20 +326,24 @@ def test_container_at_keys(on_device): def test_container_combine(on_device): - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([4], device=on_device), - "b": { - "c": ivy.array([5], device=on_device), - "e": ivy.array([6], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([4], device=on_device), + "b": { + "c": ivy.array([5], device=on_device), + "e": ivy.array([6], device=on_device), + }, + } + ) container_comb = ivy.Container.cont_combine(container_0, container_1) assert np.equal(ivy.to_numpy(container_comb.a), np.array([4])) assert np.equal(ivy.to_numpy(container_comb.b.c), np.array([5])) @@ -375,21 +391,25 @@ def test_container_common_key_chains(on_device): def test_container_cont_inplace_update(on_device): - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([1], device=on_device), - "d": ivy.array([2], device=on_device), - }, - }) + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([1], device=on_device), + "d": ivy.array([2], device=on_device), + }, + } + ) id0 = id(container0) - container1 = Container({ - "a": ivy.array([0], device=on_device), - "b": { - "c": ivy.array([0], device=on_device), - "d": ivy.array([0], device=on_device), - }, - }) + container1 = Container( + { + "a": ivy.array([0], device=on_device), + "b": { + "c": ivy.array([0], device=on_device), + "d": ivy.array([0], device=on_device), + }, + } + ) id1 = id(container1) assert ivy.Container.cont_all_false(container0.all_equal(container1)) container0.inplace_update(container1) @@ -425,10 +445,12 @@ def test_container_contains(on_device): assert not partial_sub_cont.cont_contains_sub_container(container, partial=True) # sub-structure - sub_struc = Container({ - "c": ivy.array([3.0], device=on_device), - "d": ivy.array([4.0], device=on_device), - }) + sub_struc = Container( + { + "c": ivy.array([3.0], device=on_device), + "d": ivy.array([4.0], device=on_device), + } + ) assert not container.cont_contains_sub_container(sub_struc) assert sub_struc not in container assert container.cont_contains_sub_structure(sub_struc) @@ -585,30 +607,36 @@ def test_container_deep_copy(on_device): def test_container_depth(on_device): - cont_depth1 = Container({ - "a": ivy.array([1], device=on_device), "b": ivy.array([2], device=on_device) - }) + cont_depth1 = Container( + {"a": ivy.array([1], device=on_device), "b": ivy.array([2], device=on_device)} + ) assert cont_depth1.cont_max_depth == 1 - cont_depth2 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) + cont_depth2 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) assert cont_depth2.cont_max_depth == 2 - cont_depth3 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": {"d": ivy.array([2], device=on_device)}, - "e": ivy.array([3], device=on_device), - }, - }) + cont_depth3 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": {"d": ivy.array([2], device=on_device)}, + "e": ivy.array([3], device=on_device), + }, + } + ) assert cont_depth3.cont_max_depth == 3 - cont_depth4 = Container({ - "a": ivy.array([1], device=on_device), - "b": {"c": {"d": {"e": ivy.array([2], device=on_device)}}}, - }) + cont_depth4 = Container( + { + "a": ivy.array([1], device=on_device), + "b": {"c": {"d": {"e": ivy.array([2], device=on_device)}}}, + } + ) assert cont_depth4.cont_max_depth == 4 @@ -626,20 +654,24 @@ def test_container_dev_str(on_device): def test_container_diff(on_device): # all different arrays - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([4], device=on_device), - "b": { - "c": ivy.array([5], device=on_device), - "d": ivy.array([6], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([4], device=on_device), + "b": { + "c": ivy.array([5], device=on_device), + "d": ivy.array([6], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a.diff_0), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.a.diff_1), np.array([4])) @@ -657,20 +689,24 @@ def test_container_diff(on_device): assert container_diff_same_only.cont_to_dict() == {} # some different arrays - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([5], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([5], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.b.c.diff_0), np.array([2])) @@ -692,20 +728,24 @@ def test_container_diff(on_device): assert "d" in container_diff_same_only["b"] # all different keys - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "e": ivy.array([1], device=on_device), - "f": { - "g": ivy.array([2], device=on_device), - "h": ivy.array([3], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "e": ivy.array([1], device=on_device), + "f": { + "g": ivy.array([2], device=on_device), + "h": ivy.array([3], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a.diff_0), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.b.diff_0.c), np.array([2])) @@ -723,20 +763,24 @@ def test_container_diff(on_device): assert container_diff_same_only.cont_to_dict() == {} # some different keys - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "e": ivy.array([3], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "e": ivy.array([3], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.b.c), np.array([2])) @@ -760,20 +804,24 @@ def test_container_diff(on_device): assert "e" not in container_diff_same_only["b"] # same containers - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.b.c), np.array([2])) @@ -811,13 +859,15 @@ def test_container_duplicate_array_keychains(on_device): arr1 = ivy.array([1], device=on_device) arr2 = ivy.array([2], device=on_device) container0 = Container({"a": arr1, "b": {"c": arr1, "d": arr2}}) - container1 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([1], device=on_device), - "d": ivy.array([2], device=on_device), - }, - }) + container1 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([1], device=on_device), + "d": ivy.array([2], device=on_device), + }, + } + ) res = ivy.Container.cont_duplicate_array_keychains(container0) assert res == (("a", "b/c"),) res = ivy.Container.cont_duplicate_array_keychains(container1) @@ -861,9 +911,9 @@ def test_container_find_sub_structure(on_device): top_cont = Container(dict_in) # full - sub_cont = Container({ - "c": ivy.array([4], device=on_device), "d": ivy.array([5], device=on_device) - }) + sub_cont = Container( + {"c": ivy.array([4], device=on_device), "d": ivy.array([5], device=on_device)} + ) assert not top_cont.cont_find_sub_container(sub_cont) found_kc = top_cont.cont_find_sub_structure(sub_cont) assert found_kc == "b" @@ -880,13 +930,15 @@ def test_container_find_sub_structure(on_device): def test_container_flatten_key_chains(on_device): - container = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": {"d": ivy.array([2], device=on_device)}, - "e": {"f": {"g": ivy.array([3], device=on_device)}}, - }, - }) + container = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": {"d": ivy.array([2], device=on_device)}, + "e": {"f": {"g": ivy.array([3], device=on_device)}}, + }, + } + ) # full container_flat = container.cont_flatten_key_chains() @@ -970,10 +1022,12 @@ def test_container_from_dict_w_cont_types(on_device): dict_in = { "a": ivy.array([1], device=on_device), - "b": FlatMapping({ - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }), + "b": FlatMapping( + { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + } + ), } container = Container(dict_in) assert np.allclose(ivy.to_numpy(container["a"]), np.array([1])) @@ -1053,12 +1107,15 @@ def worker_fn(in_queue, out_queue, load_size, worker_id): keep_going = in_queue.get(timeout=0.1) except queue.Empty: continue - out_queue.put({ - "a": [ - ivy.to_native(ivy.array([1.0, 2.0, 3.0], device=on_device)) - * worker_id - ] * load_size - }) + out_queue.put( + { + "a": [ + ivy.to_native(ivy.array([1.0, 2.0, 3.0], device=on_device)) + * worker_id + ] + * load_size + } + ) workers = [] in_queues = [] @@ -1190,13 +1247,15 @@ def test_container_identical(on_device): arr3 = ivy.array([3], device=on_device) container0 = Container({"a": arr1, "b": {"c": arr2, "d": arr3}}) container1 = Container({"a": arr1, "b": {"c": arr2, "d": arr3}}) - container2 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) + container2 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) container3 = Container({"b": {"d": arr3}}) container4 = Container({"d": arr3}) @@ -1219,34 +1278,40 @@ def test_container_identical(on_device): def test_container_identical_array_shapes(on_device): # without key_chains specification - container0 = Container({ - "a": ivy.array([1, 2], device=on_device), - "b": { - "c": ivy.array([2, 3, 4], device=on_device), - "d": ivy.array([3, 4, 5, 6], device=on_device), - }, - }) - container1 = Container({ - "a": ivy.array([1, 2, 3, 4], device=on_device), - "b": { - "c": ivy.array([3, 4], device=on_device), - "d": ivy.array([3, 4, 5], device=on_device), - }, - }) - container2 = Container({ - "a": ivy.array([1, 2, 3, 4], device=on_device), - "b": { - "c": ivy.array([3, 4], device=on_device), - "d": ivy.array([3, 4, 5, 6], device=on_device), - }, - }) + container0 = Container( + { + "a": ivy.array([1, 2], device=on_device), + "b": { + "c": ivy.array([2, 3, 4], device=on_device), + "d": ivy.array([3, 4, 5, 6], device=on_device), + }, + } + ) + container1 = Container( + { + "a": ivy.array([1, 2, 3, 4], device=on_device), + "b": { + "c": ivy.array([3, 4], device=on_device), + "d": ivy.array([3, 4, 5], device=on_device), + }, + } + ) + container2 = Container( + { + "a": ivy.array([1, 2, 3, 4], device=on_device), + "b": { + "c": ivy.array([3, 4], device=on_device), + "d": ivy.array([3, 4, 5, 6], device=on_device), + }, + } + ) # with identical assert ivy.Container.cont_identical_array_shapes([container0, container1]) assert ivy.Container.cont_identical_array_shapes([container1, container0]) - assert ivy.Container.cont_identical_array_shapes([ - container1, container0, container1 - ]) + assert ivy.Container.cont_identical_array_shapes( + [container1, container0, container1] + ) assert not ivy.Container.cont_identical([container0, container2]) assert not ivy.Container.cont_identical([container1, container2]) assert not ivy.Container.cont_identical([container0, container1, container2]) @@ -1264,43 +1329,51 @@ def test_container_identical_configs(on_device): # without identical assert not ivy.Container.cont_identical_configs([container1, container2]) - assert not ivy.Container.cont_identical_configs([ - container1, container0, container2 - ]) + assert not ivy.Container.cont_identical_configs( + [container1, container0, container2] + ) def test_container_identical_structure(on_device): # without key_chains specification - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container1 = Container({ - "a": ivy.array([3], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([5], device=on_device), - }, - }) - container2 = Container({ - "a": ivy.array([3], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([5], device=on_device), + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container1 = Container( + { + "a": ivy.array([3], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([5], device=on_device), + }, + } + ) + container2 = Container( + { + "a": ivy.array([3], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([5], device=on_device), + "e": ivy.array([6], device=on_device), + }, + } + ) + container3 = Container( + { + "a": ivy.array([3], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([5], device=on_device), + }, "e": ivy.array([6], device=on_device), - }, - }) - container3 = Container({ - "a": ivy.array([3], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([5], device=on_device), - }, - "e": ivy.array([6], device=on_device), - }) + } + ) container4 = Container({"b": {"d": ivy.array([4], device=on_device)}}) container5 = Container({"d": ivy.array([4], device=on_device)}) @@ -1313,9 +1386,9 @@ def test_container_identical_structure(on_device): assert not ivy.Container.cont_identical_structure([container2, container3]) assert not ivy.Container.cont_identical_structure([container0, container3]) assert not ivy.Container.cont_identical_structure([container1, container2]) - assert not ivy.Container.cont_identical_structure([ - container1, container0, container2 - ]) + assert not ivy.Container.cont_identical_structure( + [container1, container0, container2] + ) # partial assert ivy.Container.cont_identical_structure( @@ -1376,22 +1449,26 @@ def test_container_if_exists(on_device): def test_container_inplace(on_device): - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([1], device=on_device), - "d": ivy.array([2], device=on_device), - }, - }) + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([1], device=on_device), + "d": ivy.array([2], device=on_device), + }, + } + ) const = 3 arr = ivy.array([1], device=on_device) - container1 = Container({ - "a": ivy.array([3], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([5], device=on_device), - }, - }) + container1 = Container( + { + "a": ivy.array([3], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([5], device=on_device), + }, + } + ) special_funcs = [ "__add__", @@ -1443,20 +1520,24 @@ def test_container_key_chains_containing(include_empty, on_device): def test_container_list_join(on_device): - container_0 = Container({ - "a": [ivy.array([1], device=on_device)], - "b": { - "c": [ivy.array([2], device=on_device)], - "d": [ivy.array([3], device=on_device)], - }, - }) - container_1 = Container({ - "a": [ivy.array([4], device=on_device)], - "b": { - "c": [ivy.array([5], device=on_device)], - "d": [ivy.array([6], device=on_device)], - }, - }) + container_0 = Container( + { + "a": [ivy.array([1], device=on_device)], + "b": { + "c": [ivy.array([2], device=on_device)], + "d": [ivy.array([3], device=on_device)], + }, + } + ) + container_1 = Container( + { + "a": [ivy.array([4], device=on_device)], + "b": { + "c": [ivy.array([5], device=on_device)], + "d": [ivy.array([6], device=on_device)], + }, + } + ) container_list_joined = ivy.Container.cont_list_join([container_0, container_1]) assert np.allclose(ivy.to_numpy(container_list_joined["a"][0]), np.array([1])) assert np.allclose(ivy.to_numpy(container_list_joined.a[0]), np.array([1])) @@ -1473,20 +1554,24 @@ def test_container_list_join(on_device): def test_container_list_stack(on_device): - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([4], device=on_device), - "b": { - "c": ivy.array([5], device=on_device), - "d": ivy.array([6], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([4], device=on_device), + "b": { + "c": ivy.array([5], device=on_device), + "d": ivy.array([6], device=on_device), + }, + } + ) container_list_stacked = ivy.Container.cont_list_stack( [container_0, container_1], 0 ) @@ -1595,10 +1680,12 @@ def test_container_map(inplace, on_device): assert "b/d" not in container_mapped # with sequences - container_orig = Container({ - "a": ivy.array([1], device=on_device), - "b": [ivy.array([2], device=on_device), ivy.array([3], device=on_device)], - }) + container_orig = Container( + { + "a": ivy.array([1], device=on_device), + "b": [ivy.array([2], device=on_device), ivy.array([3], device=on_device)], + } + ) container = container_orig.cont_deep_copy() container_mapped = container.cont_map( lambda x, _: x + 1, inplace=inplace, map_sequences=True @@ -1613,13 +1700,15 @@ def test_container_map(inplace, on_device): @pytest.mark.parametrize("inplace", [True, False]) def test_container_map_sub_conts(inplace, on_device): # without key_chains specification - container_orig = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) + container_orig = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) def _add_e_attr(cont_in): cont_in.e = ivy.array([4], device=on_device) @@ -1651,20 +1740,24 @@ def _add_e_attr(cont_in): def test_container_multi_map(on_device): # without key_chains specification - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container1 = Container({ - "a": ivy.array([3], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([5], device=on_device), - }, - }) + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container1 = Container( + { + "a": ivy.array([3], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([5], device=on_device), + }, + } + ) # with key_chains to apply container_mapped = ivy.Container.cont_multi_map( @@ -1678,20 +1771,24 @@ def test_container_multi_map(on_device): assert np.allclose(ivy.to_numpy(container_mapped.b.d), np.array([[8]])) # with sequences - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": [ - ivy.array([2], device=on_device), - ivy.array([3], device=on_device), - ], - }) - container1 = Container({ - "a": ivy.array([3], device=on_device), - "b": [ - ivy.array([4], device=on_device), - ivy.array([5], device=on_device), - ], - }) + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": [ + ivy.array([2], device=on_device), + ivy.array([3], device=on_device), + ], + } + ) + container1 = Container( + { + "a": ivy.array([3], device=on_device), + "b": [ + ivy.array([4], device=on_device), + ivy.array([5], device=on_device), + ], + } + ) container_mapped = ivy.Container.cont_multi_map( lambda x, _: x[0] + x[1], @@ -1769,17 +1866,21 @@ def test_container_overwrite_at_key_chain(on_device): def test_container_overwrite_at_key_chains(on_device): - container = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - target_container = Container({ - "a": ivy.array([4], device=on_device), - "b": {"d": ivy.array([5], device=on_device)}, - }) + container = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + target_container = Container( + { + "a": ivy.array([4], device=on_device), + "b": {"d": ivy.array([5], device=on_device)}, + } + ) new_container = container.cont_overwrite_at_key_chains( target_container, inplace=False ) @@ -1949,17 +2050,19 @@ def _test_bc_exception(container_in): def test_container_prune_key_from_key_chains(on_device): - container = Container({ - "Ayy": ivy.array([1], device=on_device), - "Bee": { - "Cee": ivy.array([2], device=on_device), - "Dee": ivy.array([3], device=on_device), - }, - "Beh": { - "Ceh": ivy.array([4], device=on_device), - "Deh": ivy.array([5], device=on_device), - }, - }) + container = Container( + { + "Ayy": ivy.array([1], device=on_device), + "Bee": { + "Cee": ivy.array([2], device=on_device), + "Dee": ivy.array([3], device=on_device), + }, + "Beh": { + "Ceh": ivy.array([4], device=on_device), + "Deh": ivy.array([5], device=on_device), + }, + } + ) # absolute container_pruned = container.cont_prune_key_from_key_chains("Bee") @@ -2036,14 +2139,16 @@ def _test_bd_exception(container_in): def test_container_prune_keys_from_key_chains(on_device): - container = Container({ - "Ayy": ivy.array([1], device=on_device), - "Bee": { - "Cee": ivy.array([2], device=on_device), - "Dee": ivy.array([3], device=on_device), - }, - "Eee": {"Fff": ivy.array([4], device=on_device)}, - }) + container = Container( + { + "Ayy": ivy.array([1], device=on_device), + "Bee": { + "Cee": ivy.array([2], device=on_device), + "Dee": ivy.array([3], device=on_device), + }, + "Eee": {"Fff": ivy.array([4], device=on_device)}, + } + ) # absolute container_pruned = container.cont_prune_keys_from_key_chains(["Bee", "Eee"]) @@ -2073,20 +2178,24 @@ def test_container_prune_keys_from_key_chains(on_device): def test_container_reduce(on_device): - container_a = ivy.Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_b = ivy.Container({ - "a": ivy.array([2], device=on_device), - "b": { - "c": ivy.array([4], device=on_device), - "d": ivy.array([6], device=on_device), - }, - }) + container_a = ivy.Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_b = ivy.Container( + { + "a": ivy.array([2], device=on_device), + "b": { + "c": ivy.array([4], device=on_device), + "d": ivy.array([6], device=on_device), + }, + } + ) res = ivy.Container.cont_reduce([container_a, container_b], lambda x: x[0] + x[1]) assert np.allclose(ivy.to_numpy(res.a), np.array([3.0])) assert np.allclose(ivy.to_numpy(res.b.c), np.array([6])) @@ -2094,13 +2203,15 @@ def test_container_reduce(on_device): def test_container_remove_key_length_limit(on_device): - cont = Container({ - "a": ivy.array([0.0], device=on_device), - "b": { - "c": ivy.array([1.0], device=on_device), - "d": ivy.array([2.0], device=on_device), - }, - }) + cont = Container( + { + "a": ivy.array([0.0], device=on_device), + "b": { + "c": ivy.array([1.0], device=on_device), + "d": ivy.array([2.0], device=on_device), + }, + } + ) cont.cont_with_key_length_limit(5, inplace=True) default_key_length_limit = cont._key_length_limit id_cont = id(cont) @@ -2117,13 +2228,15 @@ def test_container_remove_key_length_limit(on_device): def test_container_remove_print_limit(on_device): - cont = Container({ - "a": ivy.array([0.0], device=on_device), - "b": { - "c": ivy.array([1.0], device=on_device), - "d": ivy.array([2.0], device=on_device), - }, - }) + cont = Container( + { + "a": ivy.array([0.0], device=on_device), + "b": { + "c": ivy.array([1.0], device=on_device), + "d": ivy.array([2.0], device=on_device), + }, + } + ) default_print_limit = cont._print_limit id_cont = id(cont) cont1 = cont.cont_remove_print_limit() @@ -2139,13 +2252,15 @@ def test_container_remove_print_limit(on_device): def test_container_reshape_like(on_device): - container = Container({ - "a": ivy.array([[1.0]], device=on_device), - "b": { - "c": ivy.array([[3.0], [4.0]], device=on_device), - "d": ivy.array([[5.0], [6.0], [7.0]], device=on_device), - }, - }) + container = Container( + { + "a": ivy.array([[1.0]], device=on_device), + "b": { + "c": ivy.array([[3.0], [4.0]], device=on_device), + "d": ivy.array([[5.0], [6.0], [7.0]], device=on_device), + }, + } + ) new_shapes = Container({"a": (1,), "b": {"c": (1, 2, 1), "d": (3, 1, 1)}}) # without leading shape @@ -2158,22 +2273,24 @@ def test_container_reshape_like(on_device): assert list(container_reshaped.b.d.shape) == [3, 1, 1] # with leading shape - container = Container({ - "a": ivy.array([[[1.0]], [[1.0]], [[1.0]]], device=on_device), - "b": { - "c": ivy.array( - [[[3.0], [4.0]], [[3.0], [4.0]], [[3.0], [4.0]]], device=on_device - ), - "d": ivy.array( - [ - [[5.0], [6.0], [7.0]], - [[5.0], [6.0], [7.0]], - [[5.0], [6.0], [7.0]], - ], - device=on_device, - ), - }, - }) + container = Container( + { + "a": ivy.array([[[1.0]], [[1.0]], [[1.0]]], device=on_device), + "b": { + "c": ivy.array( + [[[3.0], [4.0]], [[3.0], [4.0]], [[3.0], [4.0]]], device=on_device + ), + "d": ivy.array( + [ + [[5.0], [6.0], [7.0]], + [[5.0], [6.0], [7.0]], + [[5.0], [6.0], [7.0]], + ], + device=on_device, + ), + }, + } + ) container_reshaped = container.cont_reshape_like(new_shapes, leading_shape=[3]) assert list(container_reshaped["a"].shape) == [3, 1] assert list(container_reshaped.a.shape) == [3, 1] @@ -2184,13 +2301,15 @@ def test_container_reshape_like(on_device): def test_container_restructure(on_device): - container = Container({ - "a": ivy.array([[1, 2], [3, 4]], device=on_device), - "b": { - "c": ivy.array([[2, 4], [6, 8]], device=on_device), - "d": ivy.array([3, 6, 9, 12], device=on_device), - }, - }) + container = Container( + { + "a": ivy.array([[1, 2], [3, 4]], device=on_device), + "b": { + "c": ivy.array([[2, 4], [6, 8]], device=on_device), + "d": ivy.array([3, 6, 9, 12], device=on_device), + }, + } + ) container_restructured = container.cont_restructure( { "a": {"key_chain": "A", "pattern": "a b -> b a"}, @@ -2223,13 +2342,15 @@ def test_container_restructure(on_device): def test_container_restructure_key_chains(on_device): # single - container = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) + container = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) container_restructured = container.cont_restructure_key_chains({"a": "A"}) assert np.allclose(ivy.to_numpy(container_restructured["A"]), np.array([[1]])) assert np.allclose(ivy.to_numpy(container_restructured.A), np.array([[1]])) @@ -2239,16 +2360,18 @@ def test_container_restructure_key_chains(on_device): assert np.allclose(ivy.to_numpy(container_restructured.b.d), np.array([[3]])) # full - container = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_restructured = container.cont_restructure_key_chains({ - "a": "A", "b/c": "B/C", "b/d": "B/D" - }) + container = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_restructured = container.cont_restructure_key_chains( + {"a": "A", "b/c": "B/C", "b/d": "B/D"} + ) assert np.allclose(ivy.to_numpy(container_restructured["A"]), np.array([[1]])) assert np.allclose(ivy.to_numpy(container_restructured.A), np.array([[1]])) assert np.allclose(ivy.to_numpy(container_restructured["B/C"]), np.array([[2]])) @@ -2300,17 +2423,21 @@ def test_container_set_at_key_chain(on_device): def test_container_set_at_key_chains(on_device): - container = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - target_container = Container({ - "a": ivy.array([4], device=on_device), - "b": {"d": ivy.array([5], device=on_device)}, - }) + container = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + target_container = Container( + { + "a": ivy.array([4], device=on_device), + "b": {"d": ivy.array([5], device=on_device)}, + } + ) new_container = container.cont_set_at_key_chains(target_container, inplace=False) assert np.allclose(ivy.to_numpy(new_container["a"]), np.array([4])) assert np.allclose(ivy.to_numpy(new_container["b"]["c"]), np.array([2])) @@ -2340,9 +2467,9 @@ def test_container_set_at_keys(on_device): assert np.allclose(ivy.to_numpy(container["b"]), np.array([4])) assert not container.cont_has_key("c") # noqa assert not container.cont_has_key("d") # noqa - container = orig_container.cont_set_at_keys({ - "a": ivy.array([5], device=on_device), "c": ivy.array([6], device=on_device) - }) + container = orig_container.cont_set_at_keys( + {"a": ivy.array([5], device=on_device), "c": ivy.array([6], device=on_device)} + ) assert np.allclose(ivy.to_numpy(container["a"]), np.array([5])) assert np.allclose(ivy.to_numpy(container["b"]["c"]), np.array([6])) assert np.allclose(ivy.to_numpy(container["b"]["d"]), np.array([3])) @@ -2467,9 +2594,9 @@ def test_container_slice_keys(str_slice, on_device): # with dict, depth 0 sub_cont = Container({"a": a_val, "b": b_val, "c": c_val, "d": d_val, "e": e_val}) - cont = Container({ - "a": sub_cont, "b": sub_cont, "c": sub_cont, "d": sub_cont, "e": sub_cont - }) + cont = Container( + {"a": sub_cont, "b": sub_cont, "c": sub_cont, "d": sub_cont, "e": sub_cont} + ) cont_sliced = cont.cont_slice_keys({0: slc}) assert "a" not in cont_sliced assert Container.cont_identical([cont_sliced.b, sub_cont]) @@ -2480,9 +2607,9 @@ def test_container_slice_keys(str_slice, on_device): # with dict, depth 1 sub_cont = Container({"a": a_val, "b": b_val, "c": c_val, "d": d_val, "e": e_val}) sub_sub_cont = Container({"b": b_val, "c": c_val, "d": d_val}) - cont = Container({ - "a": sub_cont, "b": sub_cont, "c": sub_cont, "d": sub_cont, "e": sub_cont - }) + cont = Container( + {"a": sub_cont, "b": sub_cont, "c": sub_cont, "d": sub_cont, "e": sub_cont} + ) cont_sliced = cont.cont_slice_keys({1: slc}) assert Container.cont_identical([cont_sliced.a, sub_sub_cont]) assert Container.cont_identical([cont_sliced.b, sub_sub_cont]) @@ -2493,9 +2620,9 @@ def test_container_slice_keys(str_slice, on_device): # with dict, depth 0, 1 sub_cont = Container({"a": a_val, "b": b_val, "c": c_val, "d": d_val, "e": e_val}) sub_sub_cont = Container({"b": b_val, "c": c_val, "d": d_val}) - cont = Container({ - "a": sub_cont, "b": sub_cont, "c": sub_cont, "d": sub_cont, "e": sub_cont - }) + cont = Container( + {"a": sub_cont, "b": sub_cont, "c": sub_cont, "d": sub_cont, "e": sub_cont} + ) cont_sliced = cont.cont_slice_keys({0: slc, 1: slc}) assert "a" not in cont_sliced assert Container.cont_identical([cont_sliced.b, sub_sub_cont]) @@ -2506,9 +2633,9 @@ def test_container_slice_keys(str_slice, on_device): # all depths sub_cont = Container({"a": a_val, "b": b_val, "c": c_val, "d": d_val, "e": e_val}) sub_sub_cont = Container({"b": b_val, "c": c_val, "d": d_val}) - cont = Container({ - "a": sub_cont, "b": sub_cont, "c": sub_cont, "d": sub_cont, "e": sub_cont - }) + cont = Container( + {"a": sub_cont, "b": sub_cont, "c": sub_cont, "d": sub_cont, "e": sub_cont} + ) cont_sliced = cont.cont_slice_keys(slc, all_depths=True) assert "a" not in cont_sliced assert Container.cont_identical([cont_sliced.b, sub_sub_cont]) @@ -2590,20 +2717,24 @@ def test_container_split_conts(on_device): def test_container_structural_diff(on_device): # all different keys or shapes - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([[4]], device=on_device), - "b": { - "c": ivy.array([[[5]]], device=on_device), - "e": ivy.array([3], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([[4]], device=on_device), + "b": { + "c": ivy.array([[[5]]], device=on_device), + "e": ivy.array([3], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_structural_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a.diff_0), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.a.diff_1), np.array([[4]])) @@ -2621,20 +2752,24 @@ def test_container_structural_diff(on_device): assert container_diff_same_only.cont_to_dict() == {} # some different shapes - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([4], device=on_device), - "b": { - "c": ivy.array([[5]], device=on_device), - "d": ivy.array([6], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([4], device=on_device), + "b": { + "c": ivy.array([[5]], device=on_device), + "d": ivy.array([6], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_structural_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.b.c.diff_0), np.array([2])) @@ -2656,20 +2791,24 @@ def test_container_structural_diff(on_device): assert "d" in container_diff_same_only["b"] # all different keys - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "e": ivy.array([4], device=on_device), - "f": { - "g": ivy.array([5], device=on_device), - "h": ivy.array([6], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "e": ivy.array([4], device=on_device), + "f": { + "g": ivy.array([5], device=on_device), + "h": ivy.array([6], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_structural_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a.diff_0), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.b.diff_0.c), np.array([2])) @@ -2687,20 +2826,24 @@ def test_container_structural_diff(on_device): assert container_diff_same_only.cont_to_dict() == {} # some different keys - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([4], device=on_device), - "b": { - "c": ivy.array([5], device=on_device), - "e": ivy.array([6], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([4], device=on_device), + "b": { + "c": ivy.array([5], device=on_device), + "e": ivy.array([6], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_structural_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.b.c), np.array([2])) @@ -2724,20 +2867,24 @@ def test_container_structural_diff(on_device): assert "e" not in container_diff_same_only["b"] # all same - container_0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([2], device=on_device), - "d": ivy.array([3], device=on_device), - }, - }) - container_1 = Container({ - "a": ivy.array([4], device=on_device), - "b": { - "c": ivy.array([5], device=on_device), - "d": ivy.array([6], device=on_device), - }, - }) + container_0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([2], device=on_device), + "d": ivy.array([3], device=on_device), + }, + } + ) + container_1 = Container( + { + "a": ivy.array([4], device=on_device), + "b": { + "c": ivy.array([5], device=on_device), + "d": ivy.array([6], device=on_device), + }, + } + ) container_diff = ivy.Container.cont_structural_diff(container_0, container_1) assert np.equal(ivy.to_numpy(container_diff.a), np.array([1])) assert np.equal(ivy.to_numpy(container_diff.b.c), np.array([2])) @@ -2879,16 +3026,18 @@ def test_container_to_and_from_disk_as_pickled(on_device): def test_container_to_dict(on_device): - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([True], device=on_device), - "d": { - "g": ivy.array([2.0], device=on_device), - "h": ivy.array([3], device=on_device), + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([True], device=on_device), + "d": { + "g": ivy.array([2.0], device=on_device), + "h": ivy.array([3], device=on_device), + }, }, - }, - }) + } + ) res = ivy.Container.cont_to_dict(container0) assert res == {"a": 1, "b": {"c": True, "d": {"g": 2.0, "h": 3}}} @@ -3020,16 +3169,18 @@ def test_container_to_iterator_values(include_empty, on_device): def test_container_to_nested_list(on_device): - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([True], device=on_device), - "d": { - "g": ivy.array([2.0], device=on_device), - "h": ivy.array([3], device=on_device), + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([True], device=on_device), + "d": { + "g": ivy.array([2.0], device=on_device), + "h": ivy.array([3], device=on_device), + }, }, - }, - }) + } + ) res = ivy.Container.cont_to_nested_list(container0) assert res == [1, [True, [2.0, 3]]] @@ -3054,13 +3205,15 @@ def test_container_trim_key(on_device): def test_container_try_kc(on_device): - cont = Container({ - "a": ivy.array([0.0], device=on_device), - "b": { - "c": ivy.array([1.0], device=on_device), - "d": ivy.array([2.0], device=on_device), - }, - }) + cont = Container( + { + "a": ivy.array([0.0], device=on_device), + "b": { + "c": ivy.array([1.0], device=on_device), + "d": ivy.array([2.0], device=on_device), + }, + } + ) assert cont.cont_try_kc("a") == cont.a assert cont.cont_try_kc("b/c") == cont.b.c assert cont.cont_try_kc("b/d") == cont.b.d @@ -3073,21 +3226,25 @@ def test_container_unify(on_device): dev0 = on_device on_devices.append(dev0) conts = {} - conts[dev0] = Container({ - "a": ivy.array([1], device=dev0), - "b": {"c": ivy.array([2], device=dev0), "d": ivy.array([3], device=dev0)}, - }) + conts[dev0] = Container( + { + "a": ivy.array([1], device=dev0), + "b": {"c": ivy.array([2], device=dev0), "d": ivy.array([3], device=dev0)}, + } + ) if "gpu" in on_device and ivy.num_gpus() > 1: idx = ivy.num_gpus() - 1 dev1 = on_device[:-1] + str(idx) on_devices.append(dev1) - conts[dev1] = Container({ - "a": ivy.array([4], device=dev1), - "b": { - "c": ivy.array([5], device=dev1), - "d": ivy.array([6], device=dev1), - }, - }) + conts[dev1] = Container( + { + "a": ivy.array([4], device=dev1), + "b": { + "c": ivy.array([5], device=dev1), + "d": ivy.array([6], device=dev1), + }, + } + ) # test container_unified = ivy.Container.cont_unify(conts, dev0, "concat", 0) @@ -3122,13 +3279,15 @@ def test_container_unstack_conts(on_device): def test_container_with_default_key_color(on_device): - cont = Container({ - "a": ivy.array([0.0], device=on_device), - "b": { - "c": ivy.array([1.0], device=on_device), - "d": ivy.array([2.0], device=on_device), - }, - }) + cont = Container( + { + "a": ivy.array([0.0], device=on_device), + "b": { + "c": ivy.array([1.0], device=on_device), + "d": ivy.array([2.0], device=on_device), + }, + } + ) default_default_key_color = cont._default_key_color id_cont = id(cont) cont1 = cont.cont_with_default_key_color("red") @@ -3160,13 +3319,15 @@ def test_container_with_entries_as_lists(on_device): def test_container_with_ivy_backend(on_device): - container0 = Container({ - "a": ivy.array([1], device=on_device), - "b": { - "c": ivy.array([1], device=on_device), - "d": ivy.array([2], device=on_device), - }, - }) + container0 = Container( + { + "a": ivy.array([1], device=on_device), + "b": { + "c": ivy.array([1], device=on_device), + "d": ivy.array([2], device=on_device), + }, + } + ) id_container0 = id(container0) container0 = ivy.Container.cont_with_ivy_backend(container0, "numpy") assert container0.cont_config["ivyh"] == "numpy" @@ -3178,13 +3339,15 @@ def test_container_with_ivy_backend(on_device): def test_container_with_key_length_limit(on_device): - cont = Container({ - "a": ivy.array([0.0], device=on_device), - "b": { - "c": ivy.array([1.0], device=on_device), - "d": ivy.array([2.0], device=on_device), - }, - }) + cont = Container( + { + "a": ivy.array([0.0], device=on_device), + "b": { + "c": ivy.array([1.0], device=on_device), + "d": ivy.array([2.0], device=on_device), + }, + } + ) default_key_length_limit = cont._key_length_limit id_cont = id(cont) cont1 = cont.cont_with_key_length_limit(5) @@ -3200,13 +3363,15 @@ def test_container_with_key_length_limit(on_device): def test_container_with_print_indent(on_device): - cont = Container({ - "a": ivy.array([0.0], device=on_device), - "b": { - "c": ivy.array([1.0], device=on_device), - "d": ivy.array([2.0], device=on_device), - }, - }) + cont = Container( + { + "a": ivy.array([0.0], device=on_device), + "b": { + "c": ivy.array([1.0], device=on_device), + "d": ivy.array([2.0], device=on_device), + }, + } + ) default_print_indent = cont._print_indent id_cont = id(cont) cont1 = cont.cont_with_print_indent(default_print_indent + 5) @@ -3222,13 +3387,15 @@ def test_container_with_print_indent(on_device): def test_container_with_print_limit(on_device): - cont = Container({ - "a": ivy.array([0.0], device=on_device), - "b": { - "c": ivy.array([1.0], device=on_device), - "d": ivy.array([2.0], device=on_device), - }, - }) + cont = Container( + { + "a": ivy.array([0.0], device=on_device), + "b": { + "c": ivy.array([1.0], device=on_device), + "d": ivy.array([2.0], device=on_device), + }, + } + ) default_print_limit = cont._print_limit id_cont = id(cont) cont1 = cont.cont_with_print_limit(default_print_limit + 5) @@ -3243,13 +3410,15 @@ def test_container_with_print_limit(on_device): def test_container_with_print_line_spacing(on_device): - cont = Container({ - "a": ivy.array([0.0], device=on_device), - "b": { - "c": ivy.array([1.0], device=on_device), - "d": ivy.array([2.0], device=on_device), - }, - }) + cont = Container( + { + "a": ivy.array([0.0], device=on_device), + "b": { + "c": ivy.array([1.0], device=on_device), + "d": ivy.array([2.0], device=on_device), + }, + } + ) default_print_line_spacing = cont._print_line_spacing id_cont = id(cont) cont1 = cont.cont_with_print_line_spacing(default_print_line_spacing + 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 1e2efc8fdb98c..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 @@ -7,9 +7,9 @@ @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([ - ivy.prod(ivy.shape(f)) for f in tucker_tensor[1] - ]) + true_n_param = ivy.prod(ivy.shape(tucker_tensor[0])) + ivy.sum( + [ivy.prod(ivy.shape(f)) for f in tucker_tensor[1]] + ) n_param = tucker_tensor.n_param assert np.allclose(n_param, true_n_param) 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 b13bf4d6915b1..2c379e20e8b51 100644 --- a/ivy_tests/test_ivy/test_misc/test_handle_exceptions.py +++ b/ivy_tests/test_ivy/test_misc/test_handle_exceptions.py @@ -67,15 +67,17 @@ def test_non_ivy_errors_mapping(e, to_be_raised): @given( - e=st.sampled_from([ - Exception, - ZeroDivisionError, - BufferError, - AssertionError, - ImportError, - KeyError, - LookupError, - ]) + e=st.sampled_from( + [ + Exception, + ZeroDivisionError, + BufferError, + AssertionError, + ImportError, + KeyError, + LookupError, + ] + ) ) def test_non_ivy_errors_raising(e): with pytest.raises(IvyBackendException): diff --git a/ivy_tests/test_ivy/test_misc/test_shape.py b/ivy_tests/test_ivy/test_misc/test_shape.py index f20c34bb3a386..7be8231d909d4 100644 --- a/ivy_tests/test_ivy/test_misc/test_shape.py +++ b/ivy_tests/test_ivy/test_misc/test_shape.py @@ -1,24 +1,39 @@ -from hypothesis import assume, strategies as st -import numpy as np +from hypothesis import strategies as st +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"] + + +# --- Helpers --- # +# --------------- # + + +@st.composite +def shape_and_index(draw): + shape = draw(helpers.get_shape()) + index = draw( + st.integers(min_value=0, max_value=len(shape) - 1) + if len(shape) > 0 + else st.just(0) + ) + return shape, index + + @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,33 +42,28 @@ 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, ) @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__bool__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=st.one_of(st.just(("bool",)), helpers.get_dtypes("integer")), - max_num_dims=0, - min_value=0, - max_value=1, - ), + shape=helpers.get_shape(min_num_dims=0), ) def test_shape__bool__( - dtype_and_x, + shape, method_name, class_name, ground_truth_backend, @@ -62,15 +72,14 @@ def test_shape__bool__( 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, + init_all_as_kwargs_np={"shape_tup": shape}, + init_input_dtypes=DUMMY_DTYPE, method_input_dtypes=[], method_all_as_kwargs_np={}, class_name=class_name, @@ -79,15 +88,14 @@ def test_shape__bool__( @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__eq__", - 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__eq__( - dtype_and_x, + shape_1, + shape_2, method_name, class_name, ground_truth_backend, @@ -96,32 +104,30 @@ def test_shape__eq__( 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_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, ) @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,31 +136,28 @@ 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, ) @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__getitem__", - dtypes_x_query=helpers.dtype_array_query( - available_dtypes=helpers.get_dtypes("valid"), - allow_neg_step=False, - ), + shape_index=shape_and_index(), ) def test_shape__getitem__( - dtypes_x_query, + shape_index, init_flags, method_flags, method_name, @@ -163,16 +166,16 @@ def test_shape__getitem__( ground_truth_backend, on_device, ): - dtypes, x, query = dtypes_x_query + shape, query = shape_index helpers.test_method( on_device=on_device, backend_to_test=backend_fw, ground_truth_backend=ground_truth_backend, init_flags=init_flags, method_flags=method_flags, - init_all_as_kwargs_np={"shape": x[0]}, - init_input_dtypes=[dtypes[0]], - method_input_dtypes=[dtypes[1]], + init_all_as_kwargs_np={"shape_tup": shape}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=DUMMY_DTYPE, method_all_as_kwargs_np={"key": query}, class_name=class_name, method_name=method_name, @@ -180,15 +183,12 @@ def test_shape__getitem__( @handle_method( - method_tree="Shape.__gt__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - num_arrays=2, - shared_dtype=True, - ), + init_tree=CLASS_TREE, + method_tree="Shape.__getnewargs__", + shape=helpers.get_shape(), ) -def test_shape__gt__( - dtype_and_x, +def test_shape__getnewargs__( + shape, method_name, class_name, ground_truth_backend, @@ -197,34 +197,30 @@ def test_shape__gt__( 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}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=[], + method_all_as_kwargs_np={}, class_name=class_name, method_name=method_name, ) @handle_method( - method_tree="Shape.__int__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("numeric"), - max_num_dims=0, - min_value=-1e15, - max_value=1e15, - ), - method_container_flags=st.just([False]), + init_tree=CLASS_TREE, + method_tree="Shape.__gt__", + shape_1=helpers.get_shape(), + shape_2=helpers.get_shape(), ) -def test_shape__int__( - dtype_and_x, +def test_shape__gt__( + shape_1, + shape_2, method_name, class_name, ground_truth_backend, @@ -233,32 +229,28 @@ def test_shape__int__( 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=[], - method_all_as_kwargs_np={}, + 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, ) @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__iter__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("integer"), - min_dim_size=2, - min_num_dims=1, - ), + shape=helpers.get_shape(), ) def test_shape__iter__( - dtype_and_x, + shape, method_name, class_name, ground_truth_backend, @@ -267,16 +259,15 @@ def test_shape__iter__( 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, + init_all_as_kwargs_np={"shape_tup": shape}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=DUMMY_DTYPE, method_all_as_kwargs_np={}, class_name=class_name, method_name=method_name, @@ -284,15 +275,14 @@ def test_shape__iter__( @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__le__", - 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__le__( - dtype_and_x, + shape_1, + shape_2, method_name, class_name, ground_truth_backend, @@ -301,32 +291,28 @@ def test_shape__le__( 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, ) @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__len__", - dtype_and_x=helpers.dtype_and_values( - available_dtypes=helpers.get_dtypes("integer"), - min_dim_size=2, - min_num_dims=1, - ), + shape=helpers.get_shape(), ) def test_shape__len__( - dtype_and_x, + shape, method_name, class_name, backend_fw, @@ -335,16 +321,15 @@ def test_shape__len__( 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, + init_all_as_kwargs_np={"shape_tup": shape}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=DUMMY_DTYPE, method_all_as_kwargs_np={}, class_name=class_name, method_name=method_name, @@ -352,15 +337,14 @@ def test_shape__len__( @handle_method( + init_tree=CLASS_TREE, method_tree="Shape.__lt__", - 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__lt__( - dtype_and_x, + shape_1, + shape_2, method_name, class_name, ground_truth_backend, @@ -369,73 +353,30 @@ def test_shape__lt__( 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]}, - class_name=class_name, - method_name=method_name, - ) - - -@handle_method( - method_tree="Shape.__mod__", - 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, - ), -) -def test_shape__mod__( - dtype_and_x, - method_name, - class_name, - backend_fw, - ground_truth_backend, - init_flags, - method_flags, - on_device, -): - dtype, x = dtype_and_x - assume(not np.any(np.isclose(x[1], 0))) 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_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, ) @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,148 +385,62 @@ 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, - method_name, - class_name, - backend_fw, - ground_truth_backend, - 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={"shape": x[0]}, - init_input_dtypes=dtype, - method_input_dtypes=dtype, - method_all_as_kwargs_np={"other": x[1]}, - class_name=class_name, - method_name=method_name, - ) - - -@handle_method( - method_tree="Shape.__rdiv__", - 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, - ), -) -def test_shape__rdiv__( - dtype_and_x, + shape_1, + shape_2, method_name, class_name, - ground_truth_backend, backend_fw, - init_flags, - method_flags, - on_device, -): - dtype, x = dtype_and_x - assume(not np.any(np.isclose(x[0], 0))) - 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]}, - class_name=class_name, - method_name=method_name, - ) - - -@handle_method( - method_tree="Shape.__rmod__", - 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, - ), -) -def test_shape__rmod__( - dtype_and_x, - method_name, - class_name, ground_truth_backend, - backend_fw, init_flags, method_flags, on_device, ): - dtype, x = dtype_and_x - assume(not np.any(np.isclose(x[0], 0))) 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_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, ) @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, @@ -594,72 +449,38 @@ def test_shape__rmul__( 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( - method_tree="Shape.__rsub__", - 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, - ), -) -def test_shape__rsub__( - dtype_and_x, - method_name, - class_name, - backend_fw, - ground_truth_backend, - 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={"shape": x[0]}, - init_input_dtypes=dtype, - method_input_dtypes=dtype, - method_all_as_kwargs_np={"other": x[1]}, - 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 @handle_method( - method_tree="Shape.__sub__", - 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, - ), + init_tree=CLASS_TREE, + method_tree="Shape.numel", + shape=helpers.get_shape(), ) -def test_shape__sub__( - dtype_and_x, +def test_shape_numel( + shape, method_name, class_name, ground_truth_backend, @@ -668,17 +489,16 @@ def test_shape__sub__( 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}, + init_input_dtypes=DUMMY_DTYPE, + method_input_dtypes=[], + method_all_as_kwargs_np={}, class_name=class_name, method_name=method_name, ) diff --git a/ivy_tests/test_ivy/test_stateful/test_converters.py b/ivy_tests/test_ivy/test_stateful/test_converters.py index 037ca20c0fd84..693017eb44c06 100644 --- a/ivy_tests/test_ivy/test_stateful/test_converters.py +++ b/ivy_tests/test_ivy/test_stateful/test_converters.py @@ -309,9 +309,6 @@ def test_from_jax_module(bs_ic_oc, from_class_and_args, module_type, backend_fw) pytest.skip() batch_shape, input_channels, output_channels = bs_ic_oc - - # using ivy_backend.utils.backend.ContextManager instead of update_backend, - # because with_backend doesn't work here with ivy.utils.backend.ContextManager(backend_fw) as ivy_backend: x = ivy_backend.astype( ivy_backend.linspace( @@ -321,58 +318,50 @@ def test_from_jax_module(bs_ic_oc, from_class_and_args, module_type, backend_fw) ), "float32", ) - native_module_class = NATIVE_MODULES[ivy_backend.current_backend_str()][ - module_type - ] - module_converter = FROM_CONVERTERS[ivy_backend.current_backend_str()][ - module_type - ] - module_converter = get_converter( - ivy_backend, FROM_CONVERTERS[ivy_backend.current_backend_str()][module_type] + native_module_class = NATIVE_MODULES["jax"][module_type] + module_converter = FROM_CONVERTERS["jax"][module_type] + module_converter = get_converter(ivy, FROM_CONVERTERS["jax"][module_type]) + if from_class_and_args: + ivy_module = module_converter( + native_module_class, + instance_args=[x], + constructor_kwargs={ + "in_size": input_channels, + "out_size": output_channels, + }, ) + else: + if module_type == "haiku": - if from_class_and_args: - ivy_module = module_converter( - native_module_class, - instance_args=[x], - constructor_kwargs={ - "in_size": input_channels, - "out_size": output_channels, - }, - ) - else: - if module_type == "haiku": - - def forward_fn(*a, **kw): - model = native_module_class(input_channels, output_channels) - return model(ivy_backend.to_native(x)) + def forward_fn(*a, **kw): + model = native_module_class(input_channels, output_channels) + return model(x.data) - native_module = hk.transform(forward_fn) - else: - native_module = native_module_class( - in_size=input_channels, out_size=output_channels - ) + native_module = hk.transform(forward_fn) + else: + native_module = native_module_class( + in_size=input_channels, out_size=output_channels + ) - fw_kwargs = {} - if module_type == "haiku": - fw_kwargs["params_hk"] = native_module.init(0, x) - else: - fw_kwargs["params_fx"] = native_module.init( - jax.random.PRNGKey(0), ivy_backend.to_native(x) - ) - ivy_module = module_converter(native_module, **fw_kwargs) + fw_kwargs = {} + if module_type == "haiku": + fw_kwargs["params_hk"] = native_module.init(0, x) + else: + fw_kwargs["params_fx"] = native_module.init(jax.random.PRNGKey(0), x.data) + ivy_module = module_converter(native_module, **fw_kwargs) - def loss_fn(v_=None): - out = ivy_module(x, v=v_) - return ivy_backend.mean(out) + def loss_fn(v_=None): + out = ivy_module(x, v=v_) + return ivy_backend.mean(out) - # train - loss_tm1 = 1e12 - loss = None - grads = None - loss_fn() # for on-call mode + # train + loss_tm1 = 1e12 + loss = None + grads = None + loss_fn() # for on-call mode - for i in range(10): + with ivy.utils.backend.ContextManager(backend_fw) as ivy_backend: + for _ in range(10): loss, grads = ivy_backend.execute_with_gradients(loss_fn, ivy_module.v) ivy_module.v = ivy_backend.gradient_descent_update( ivy_module.v, grads, 1e-3 diff --git a/ivy_tests/test_ivy/test_stateful/test_layers.py b/ivy_tests/test_ivy/test_stateful/test_layers.py index 1fae883a74d60..512857dbee31f 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 @@ -1151,6 +1156,45 @@ def test_fft_layer( ) +@handle_method( + method_tree="IDct.__call__", + dtype_x_and_args=_valid_dct(), +) +def test_idct( + *, + dtype_x_and_args, + test_gradients, + on_device, + class_name, + method_name, + ground_truth_backend, + init_flags, + method_flags, + backend_fw, +): + dtype, x, type, n, axis, norm = dtype_x_and_args + helpers.test_method( + ground_truth_backend=ground_truth_backend, + backend_to_test=backend_fw, + init_flags=init_flags, + method_flags=method_flags, + init_all_as_kwargs_np={ + "dtype": dtype[0], + "type": type, + "n": n, + "axis": axis, + "norm": norm, + "device": on_device, + }, + method_input_dtypes=dtype, + method_all_as_kwargs_np={"x": x[0]}, + class_name=class_name, + method_name=method_name, + test_gradients=test_gradients, + on_device=on_device, + ) + + # Identity @handle_method( method_tree="Identity.__call__", @@ -1555,129 +1599,131 @@ def test_multi_head_attention_layer( # # Sequential # @handle_method( method_tree="Sequential.__call__", - bs_c_target=st.sampled_from([ - ( - [1, 2], - 5, - [ + bs_c_target=st.sampled_from( + [ + ( + [1, 2], + 5, [ - [-0.34784955, 0.47909835, 0.7241975, -0.82175905, -0.43836743], - [-0.34784955, 0.47909835, 0.7241975, -0.82175905, -0.43836743], - ] - ], - ) - ]), + [ + [-0.34784955, 0.47909835, 0.7241975, -0.82175905, -0.43836743], + [-0.34784955, 0.47909835, 0.7241975, -0.82175905, -0.43836743], + ] + ], + ) + ] + ), 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) - ), - }, - } - }) - 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, + 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, 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_modules.py b/ivy_tests/test_ivy/test_stateful/test_modules.py index 2b61e72b22645..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,191 +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 @@ -398,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: @@ -417,231 +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( @@ -910,21 +513,23 @@ def test_module_w_partial_v( ivy.linspace(ivy.zeros(batch_shape), ivy.ones(batch_shape), input_channels), "float32", ) - v = ivy.Container({ - "linear0": { - "b": _variable(ivy.random_uniform(shape=[64])), - "w": _variable(ivy.random_uniform(shape=[64, 4])), - }, - "linear1": { - "b": _variable(ivy.random_uniform(shape=[64])), - "w": _variable(ivy.random_uniform(shape=[64, 64])), - "extra": _variable(ivy.random_uniform(shape=[64, 64])), - }, - "linear2": { - "b": _variable(ivy.random_uniform(shape=[5])), - "w": _variable(ivy.random_uniform(shape=[5, 64])), - }, - }) + v = ivy.Container( + { + "linear0": { + "b": _variable(ivy.random_uniform(shape=[64])), + "w": _variable(ivy.random_uniform(shape=[64, 4])), + }, + "linear1": { + "b": _variable(ivy.random_uniform(shape=[64])), + "w": _variable(ivy.random_uniform(shape=[64, 64])), + "extra": _variable(ivy.random_uniform(shape=[64, 64])), + }, + "linear2": { + "b": _variable(ivy.random_uniform(shape=[5])), + "w": _variable(ivy.random_uniform(shape=[5, 64])), + }, + } + ) try: TrainableModule( input_channels, @@ -939,13 +544,17 @@ def test_module_w_partial_v( ) except ivy.utils.exceptions.IvyException: pass - v = ivy.Container({ - "linear0": { - "b": _variable(ivy.random_uniform(shape=[64])), - }, - "linear1": {"w": _variable(ivy.random_uniform(shape=[64, 64]))}, - "linear2": {"b": _variable(ivy.random_uniform(shape=[output_channels]))}, - }) + v = ivy.Container( + { + "linear0": { + "b": _variable(ivy.random_uniform(shape=[64])), + }, + "linear1": {"w": _variable(ivy.random_uniform(shape=[64, 64]))}, + "linear2": { + "b": _variable(ivy.random_uniform(shape=[output_channels])) + }, + } + ) try: TrainableModule(input_channels, output_channels, device=on_device, v=v) raise Exception( @@ -960,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): @@ -1089,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..8e3405cdad7d9 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 @@ -9,10 +9,8 @@ opencv-python # unpinned , mod_name=cv2 jax[cpu] # unpinned, we test for latest version now, mod_name=jax jaxlib # unpinned, we test for latest version now paddlepaddle # unpinned , mod_name=paddle -tensorflow-cpu # unpinned, we test for latest version now, mod_name=tensorflow +tensorflow-cpu==2.15.1 # pinned to 2.15.1 until keras support is added, 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..51966e031d9e9 100644 --- a/requirements/optional_apple_silicon_2.txt +++ b/requirements/optional_apple_silicon_2.txt @@ -1,5 +1,3 @@ -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 +9,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..51966e031d9e9 100644 --- a/requirements/optional_apple_silicon_gpu_2.txt +++ b/requirements/optional_apple_silicon_gpu_2.txt @@ -1,5 +1,3 @@ -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 +9,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..a8c6d5286ad2b 100644 --- a/requirements/optional_gpu.txt +++ b/requirements/optional_gpu.txt @@ -10,8 +10,6 @@ jax # unpinned, we test for latest version now 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..efeaf73b66390 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -16,3 +16,4 @@ ml-dtypes # mod_name=ml_dtypes cloudpickle gast tqdm +cryptography diff --git a/scripts/backend_generation/generate.py b/scripts/backend_generation/generate.py index ef2a7af9789f9..523ad1b6f28a7 100644 --- a/scripts/backend_generation/generate.py +++ b/scripts/backend_generation/generate.py @@ -154,9 +154,9 @@ def _should_install_backend(package_name): if ret.lower() == "y": try: # Install backend - subprocess.check_call([ - sys.executable, "-m", "pip", "install", package_name - ]) + subprocess.check_call( + [sys.executable, "-m", "pip", "install", package_name] + ) global _backend_is_installed _backend_is_installed = True with open("../../requirements/optional.txt", "a") as reqr_file: @@ -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 871ef7abbc343..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 @@ -289,15 +292,17 @@ def generate(config_file): generated_file.write(astunparse.unparse(tree_to_write)) subprocess.run(["black", "-q", backend_generation_path]) - subprocess.run([ - "autoflake", - "-i", - "--remove-all-unused-imports", - "--ignore-init-module-imports", - "--quiet", - "-r", - backend_generation_path, - ]) + subprocess.run( + [ + "autoflake", + "-i", + "--remove-all-unused-imports", + "--ignore-init-module-imports", + "--quiet", + "-r", + backend_generation_path, + ] + ) if __name__ == "__main__": diff --git a/scripts/determine_tests/array_api_det_coverage.py b/scripts/determine_tests/array_api_det_coverage.py index 0315a04139e79..cfae03436d82c 100644 --- a/scripts/determine_tests/array_api_det_coverage.py +++ b/scripts/determine_tests/array_api_det_coverage.py @@ -88,7 +88,7 @@ def main(): 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 ' + 'ARRAY_API_TESTS_MODULE="ivy" -v "$(pwd)":/ivy transpileai/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 > " diff --git a/scripts/determine_tests/determine_test_coverage.py b/scripts/determine_tests/determine_test_coverage.py index 098e0a61b9fb7..4fda545315f25 100644 --- a/scripts/determine_tests/determine_test_coverage.py +++ b/scripts/determine_tests/determine_test_coverage.py @@ -38,7 +38,7 @@ for test_backend in tqdm(test_names[start:end]): test_name, backend = test_backend.split(",") command = ( - f'docker run -v "$(pwd)":/ivy unifyai/ivy:latest timeout 30m /bin/bash -c "coverage run --source=ivy,' # noqa + f'docker run -v "$(pwd)":/ivy transpileai/ivy:latest timeout 30m /bin/bash -c "coverage run --source=ivy,' # noqa f"ivy_tests -m pytest {test_name} --num-examples 5 --backend {backend} --disable-warnings > coverage_output;coverage " # noqa f'annotate > coverage_output" ' ) diff --git a/scripts/determine_tests/determine_tests.py b/scripts/determine_tests/determine_tests.py index fb0c284001f11..399ed9c3fbe98 100644 --- a/scripts/determine_tests/determine_tests.py +++ b/scripts/determine_tests/determine_tests.py @@ -100,13 +100,13 @@ def main(): # if it is a PR, we must check that the tests added were in the files_changes if len(sys.argv) >= 3 and sys.argv[2] == "pr": relevant_added_tests = [] - subprocess.run([ - "git", "remote", "add", "upstream", "https://github.com/unifyai/ivy" - ]) + subprocess.run( + ["git", "remote", "add", "upstream", "https://github.com/unifyai/ivy"] + ) subprocess.run(["git", "fetch", "upstream"]) - lca_sha = subprocess.check_output([ - "git", "merge-base", "HEAD", "upstream/main" - ]) + lca_sha = subprocess.check_output( + ["git", "merge-base", "HEAD", "upstream/main"] + ) lca_hash = lca_sha.decode().strip() for commit in Repository(".", single=lca_hash).traverse_commits(): lca_commit = commit._c_object @@ -147,7 +147,7 @@ def main(): print("Computing Coverage:", test_backend) test_name, backend = test_backend.split(",") command = ( - f'docker run -v "$(pwd)":/ivy unifyai/ivy:latest /bin/bash -c "coverage run --source=ivy,' # noqa + f'docker run -v "$(pwd)":/ivy transpileai/ivy:latest /bin/bash -c "coverage run --source=ivy,' # noqa f"ivy_tests -m pytest {test_name} --backend {backend} --disable-warnings > coverage_output;coverage " # noqa f'annotate > coverage_output" ' ) diff --git a/scripts/duplicate.py b/scripts/duplicate.py index 589183e308222..dfa9b2dc7d866 100644 --- a/scripts/duplicate.py +++ b/scripts/duplicate.py @@ -1,8 +1,11 @@ +import ast import importlib import os import sys import glob +sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) + def get_all_functions_from_directory(root_dir, startswith="test"): if not os.path.exists(root_dir): @@ -22,7 +25,7 @@ def get_all_functions_from_directory(root_dir, startswith="test"): return functions_names -def check_duplicate(): +def check_duplicate_functional_experimental_tests(): fn_test_core = get_all_functions_from_directory( "ivy_tests/test_ivy/test_functional/test_core" ) @@ -34,11 +37,95 @@ def check_duplicate(): ) fn_ivy_test = set(fn_test_core).union(set(fn_test_nn)) common_list = fn_ivy_test.intersection(set(fn_test_experimental)) - return common_list + + # returns True if duplicate found, False if no duplicates found + return len(common_list) > 0 + + +def find_duplicate_functions(root_dir): + """Searches for any duplicate frontend functions within ivy's frontend + api.""" + fns = [] + duplicates = [] + current_class_fns = [] + exclude = [ + # functions to exclude + "dtype", + "device", + "is_leaf", + "ivy_array", + "numel", # torch.Size + "requires_grad", + "symmetrize", + # files to exclude + "base.py", + "func_wrapper.py", + "loss_functions.py", + ] + + # NOTE: Size and Tensor are currently defined in the same file, which + # causes duplication overlapping as the class defs override each + # other when doing the breadth-first ast walk. Not causing any + # problems right now (excluded some methods), but worth noting. + + for root, dirs, files in os.walk(root_dir): + for file in files: + if file.endswith(".py"): + file_path = os.path.join(root, file) + file_name = file_path.split("/")[-1] + if file_name in exclude or file_name.startswith("_"): + continue + with open(file_path, "r") as f: + tree = ast.parse(f.read()) + for node in ast.walk(tree): + if isinstance(node, ast.Module): + current_class = "" + current_class_fns = [] + if not hasattr(node, "col_offset") or node.col_offset == 0: + current_class = "" + current_class_fns = [] + if isinstance(node, ast.ClassDef): + current_class = node.name + current_class_fns = [] + if isinstance(node, ast.FunctionDef): + func_name = node.name + if ( + func_name in exclude # ignore any fns in `exclude` + or func_name.startswith( + "_" + ) # ignore any private or dunder methods + ): + continue + func_path = file_path + full_name = func_path + "::" + func_name + if ( + node.decorator_list + and hasattr(node.decorator_list[0], "id") + and node.decorator_list[0].id == "property" + ): + # ignore properties + continue + if len(current_class) == 0: + if full_name not in fns: + fns.append(full_name) + else: + duplicates.append(full_name) + else: + if full_name not in current_class_fns: + current_class_fns.append(full_name) + else: + duplicates.append(full_name) + return duplicates if __name__ == "__main__": - common_set = check_duplicate() - if len(common_set) != 0: - print("This function already exists in the functional API.") + duplicated_frontends = find_duplicate_functions("ivy/functional/frontends/") + if duplicated_frontends: + print("Duplicate functions found:") + print(duplicated_frontends) + sys.exit(1) + + if check_duplicate_functional_experimental_tests(): sys.exit(1) + + print("No duplicate functions found") diff --git a/scripts/eager_mode_benchmark/benchmark.py b/scripts/eager_mode_benchmark/benchmark.py index ba568a18de238..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 ---------- @@ -280,8 +279,7 @@ def visualize_speed_up( backends: Union[List[str], str] = "all", 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.py b/scripts/run_tests/array_api_run_tests.py index 6417b24e46444..ee145bedeb498 100644 --- a/scripts/run_tests/array_api_run_tests.py +++ b/scripts/run_tests/array_api_run_tests.py @@ -85,7 +85,7 @@ def main(): test, backend = line.split(",") backend = backend.strip("\n") coll, submod, test_fn = get_submodule(test) - command = f'docker run --rm --env IVY_BACKEND={backend} --env ARRAY_API_TESTS_MODULE="ivy" --env REDIS_URL={redis_url} --env REDIS_PASSWD={redis_pass} -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest timeout 30m python3 -m pytest {test} -k "{k_flag[backend]}" --tb=short -vv' # noqa + command = f'docker run --rm --env IVY_BACKEND={backend} --env ARRAY_API_TESTS_MODULE="ivy" --env REDIS_URL={redis_url} --env REDIS_PASSWD={redis_pass} -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/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") diff --git a/scripts/run_tests/array_api_run_tests_pr.py b/scripts/run_tests/array_api_run_tests_pr.py index 72c774b85a0e6..0248aa8705eda 100644 --- a/scripts/run_tests/array_api_run_tests_pr.py +++ b/scripts/run_tests/array_api_run_tests_pr.py @@ -26,7 +26,7 @@ def main(): 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 + command = f'docker run --rm --env IVY_BACKEND={backend} --env ARRAY_API_TESTS_MODULE="ivy" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/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") diff --git a/scripts/run_tests/helpers.py b/scripts/run_tests/helpers.py index 9d2f1a7928571..2380fb1f78ce6 100644 --- a/scripts/run_tests/helpers.py +++ b/scripts/run_tests/helpers.py @@ -4,7 +4,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"] diff --git a/scripts/run_tests/run_tests.py b/scripts/run_tests/run_tests.py index c86ac15803e5f..62e7b06e02277 100644 --- a/scripts/run_tests/run_tests.py +++ b/scripts/run_tests/run_tests.py @@ -20,9 +20,11 @@ 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}" @@ -30,6 +32,20 @@ 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 ) @@ -46,7 +62,7 @@ # pull gpu image for gpu testing if device == "gpu": - os.system("docker pull unifyai/ivy:latest-gpu") + os.system("docker pull transpileai/ivy:latest-gpu") # read the tests to be run with open("tests_to_run", "r") as f: @@ -73,7 +89,7 @@ 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( @@ -103,6 +119,7 @@ image = "unifyai/ivy:latest-gpu" device_str = " --device=gpu:0" device_access_str = " --gpus all" + os.system("docker pull transpileai/ivy:latest-gpu") os.system( f"docker run{device_access_str} --name test-container -v " @@ -112,6 +129,7 @@ command = ( "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) @@ -207,12 +225,14 @@ "_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, diff --git a/scripts/run_tests/run_tests_pr.py b/scripts/run_tests/run_tests_pr.py index 3d78479544b55..9106d13f5630d 100644 --- a/scripts/run_tests/run_tests_pr.py +++ b/scripts/run_tests/run_tests_pr.py @@ -14,7 +14,7 @@ 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_path} --skip-trace-testing --backend {backend}' # noqa + f'docker run --rm -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --tb=short {test_path} --skip-trace-testing --skip-trace-testing-each --backend {backend}' # noqa ) if ret != 0: failed = True diff --git a/scripts/run_tests_from_diff.py b/scripts/run_tests_from_diff.py new file mode 100644 index 0000000000000..02d6beb80a187 --- /dev/null +++ b/scripts/run_tests_from_diff.py @@ -0,0 +1,81 @@ +"""Script that attempts to find the test file(s) corresponding the all the +changes made in a commit (git diff stored in commit-diff.txt), and runs all the +tests it finds.""" + +import os +import re +import subprocess +import sys + + +with open("commit-diff.txt", "r") as f: + diff_lines = f.readlines() + +modified_files = set() +for line in diff_lines: + if line.startswith("diff --git a/"): + file_path = line.split(" ")[2].strip().lstrip("a/") + modified_files.add(file_path) + elif line.startswith("diff --git b/"): + file_path = line.split(" ")[2].strip().lstrip("b/") + modified_files.add(file_path) + elif line.startswith("diff --git "): + file_path = line.split(" ")[2].strip().lstrip("--git ") + modified_files.add(file_path) + +nn = [ + "activations", + "layers", + "losses", + "norms", +] +exclude = [ + "conftest", +] +test_paths = [] + +for file_path in set(modified_files): + try: + suffix = file_path.rsplit("/", 1)[1].replace(".py", "") + except IndexError: + continue + if suffix in exclude: + continue + + # some regex logic to get the correct test file for the given modified file + if "/frontends/" in file_path: + file_path = file_path.replace("/functional", "") + + if "/backends/" in file_path: + file_path = re.sub(r"/backends/.*?/", "/", file_path) + file_path = file_path.rsplit("/", 1)[0] + if suffix in nn: + file_path += f"/nn/{suffix}.py" + else: + file_path += f"/core/{suffix}.py" + + if not file_path.startswith("ivy_tests/"): + path_list = file_path.split("/") + path_list = ["test_" + p for p in path_list] + file_path = "ivy_tests/" + "/".join(path_list) + + # if the test file doesn't exist, step up a directory + # and run those tests instead (if that exists) + if not os.path.exists(file_path): + file_path = file_path.rsplit("/", 1)[0] + + if os.path.exists(file_path) and "ivy_tests/test_ivy/" in file_path: + test_paths.append(file_path) + +test_paths = set(test_paths) +print("Running tests:", test_paths) + +for test_path in test_paths: + pytest_command = ( + f"pytest {test_path} -p no:warnings --tb=short --backend jax,tensorflow,torch" + ) + print(f"Running test command: {pytest_command}") + result = subprocess.run(pytest_command, shell=True) + + if result.returncode != 0: + sys.exit(result.returncode) diff --git a/scripts/setup_tests/cron_tests.py b/scripts/setup_tests/cron_tests.py index 810401efffb48..af1045ac50bf7 100644 --- a/scripts/setup_tests/cron_tests.py +++ b/scripts/setup_tests/cron_tests.py @@ -2,17 +2,19 @@ from get_all_tests import get_all_tests -run_iter, gpu = int(sys.argv[1]), sys.argv[2] +run_iter, gpu, tracer = int(sys.argv[1]), sys.argv[2], sys.argv[3] if gpu == "true": from setup_priority_tests import main - main() + main(cron=True) 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) start = run_iter * tests_per_run end = (run_iter + 1) * tests_per_run 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 6f1f85ea30e9e..9b4c52cb947ee 100644 --- a/scripts/setup_tests/setup_priority_tests.py +++ b/scripts/setup_tests/setup_priority_tests.py @@ -1,25 +1,33 @@ +import sys from pymongo import MongoClient from get_all_tests import BACKENDS -def main(): +def main(cron=False): # connect to the database + run_id = int(sys.argv[1]) - 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"] - 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 = [] @@ -33,12 +41,31 @@ def main(): if result: frontend_test_paths.append(result["test_path"]) - # add those paths to the tests_to_run - with open("tests_to_run", "w") as write_file: - for test_path in ivy_test_paths + frontend_test_paths: - test_path = test_path.strip() - for backend in BACKENDS: - write_file.write(f"{test_path},{backend}\n") + # split the tests based on the runner + test_paths = ivy_test_paths + frontend_test_paths + test_names = [] + for i, test_path in enumerate(test_paths): + for backend in BACKENDS: + test_names.append(f"{test_path},{backend}") + + if cron: + with open("tests_to_run", "w") as write_file: + for test_name in test_names: + test_name = test_name.strip() + write_file.write(test_name + "\n") + else: + # add those paths to the tests_to_run based on the runner + tests_per_run = 10 + num_tests = len(test_names) + start = run_id * tests_per_run + end = (run_id + 1) * tests_per_run + print("Running Tests:") + with open("tests_to_run", "w") as write_file: + for i in range(start, end): + i = i % num_tests + test = test_names[i].strip() + print(test) + write_file.write(test + "\n") if __name__ == "__main__": diff --git a/scripts/shell/deploy_pypi.sh b/scripts/shell/deploy_pypi.sh index c185f62dbb87d..cb51bbcc1e196 100644 --- a/scripts/shell/deploy_pypi.sh +++ b/scripts/shell/deploy_pypi.sh @@ -1,5 +1,6 @@ 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 diff --git a/scripts/shell/run_integration_tests.sh b/scripts/shell/run_integration_tests.sh new file mode 100755 index 0000000000000..085fe66895aec --- /dev/null +++ b/scripts/shell/run_integration_tests.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +integration=$1 +target=$2 + +export IVY_KEY=$3 + +pip3 install kornia +pytest ivy_tests/test_integrations/test_$integration.py -p no:warnings --target $target diff --git a/scripts/shell/run_tests.sh b/scripts/shell/run_tests.sh index 1f75956bbbcca..3d5137b916c48 100755 --- a/scripts/shell/run_tests.sh +++ b/scripts/shell/run_tests.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm -it -v "$(pwd)":/ivy unifyai/ivy:latest python3 -m pytest ivy_tests/ +docker run --rm -it -v "$(pwd)":/ivy transpileai/ivy:latest python3 -m pytest ivy_tests/ diff --git a/scripts/shell/test_array_api.sh b/scripts/shell/test_array_api.sh index dbcf90e66d2b5..a9be851d330e1 100755 --- a/scripts/shell/test_array_api.sh +++ b/scripts/shell/test_array_api.sh @@ -8,4 +8,4 @@ fi mkdir -p .hypothesis # shellcheck disable=SC2046 -docker run --rm --env IVY_BACKEND="$1" --env ARRAY_API_TESTS_MODULE="ivy" --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v $(pwd):/ivy -v $(pwd)/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest ivy_tests/array_api_testing/test_array_api/array_api_tests/"$2".py -k "$ARRAY_API_TESTS_K_FLAG" --tb=short -vv +docker run --rm --env IVY_BACKEND="$1" --env ARRAY_API_TESTS_MODULE="ivy" --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v $(pwd):/ivy -v $(pwd)/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest ivy_tests/array_api_testing/test_array_api/array_api_tests/"$2".py -k "$ARRAY_API_TESTS_K_FLAG" --tb=short -vv diff --git a/scripts/shell/test_dependencies.sh b/scripts/shell/test_dependencies.sh index 6302c7ccfd4e2..4e73e3fb2ce4f 100755 --- a/scripts/shell/test_dependencies.sh +++ b/scripts/shell/test_dependencies.sh @@ -1,4 +1,4 @@ #!/bin/bash # shellcheck disable=SC2046 -docker run --rm -v "$(pwd)":/ivy unifyai/ivy:latest python3 ivy/test_dependencies.py -fp ivy/requirements.txt,ivy/optional.txt +docker run --rm -v "$(pwd)":/ivy transpileai/ivy:latest python3 ivy/test_dependencies.py -fp ivy/requirements.txt,ivy/optional.txt diff --git a/scripts/shell/test_experimental_core.sh b/scripts/shell/test_experimental_core.sh index e4e5de0997dfd..f2eb0f1a52d43 100755 --- a/scripts/shell/test_experimental_core.sh +++ b/scripts/shell/test_experimental_core.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_functional/test_experimental/test_core/"$2".py --tb=short +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_functional/test_experimental/test_core/"$2".py --tb=short diff --git a/scripts/shell/test_experimental_nn.sh b/scripts/shell/test_experimental_nn.sh index 52d758d04e178..fa854f62a5ca5 100755 --- a/scripts/shell/test_experimental_nn.sh +++ b/scripts/shell/test_experimental_nn.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_functional/test_experimental/test_nn/"$2".py --tb=short +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_functional/test_experimental/test_nn/"$2".py --tb=short diff --git a/scripts/shell/test_ivy_core.sh b/scripts/shell/test_ivy_core.sh index 179de1a1b5643..a2c15cb72fae4 100755 --- a/scripts/shell/test_ivy_core.sh +++ b/scripts/shell/test_ivy_core.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_functional/test_core/"$2".py --tb=short +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_functional/test_core/"$2".py --tb=short diff --git a/scripts/shell/test_ivy_nn.sh b/scripts/shell/test_ivy_nn.sh index 152560f306a52..cb578ff85276f 100755 --- a/scripts/shell/test_ivy_nn.sh +++ b/scripts/shell/test_ivy_nn.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_functional/test_nn/"$2".py --tb=short +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_functional/test_nn/"$2".py --tb=short diff --git a/scripts/shell/test_ivy_stateful.sh b/scripts/shell/test_ivy_stateful.sh index c946bc98af09d..20a4863ed9675 100755 --- a/scripts/shell/test_ivy_stateful.sh +++ b/scripts/shell/test_ivy_stateful.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_stateful/"$2".py --tb=line +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v "$(pwd)":/ivy -v "$(pwd)"/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_stateful/"$2".py --tb=line diff --git a/scripts/shell/test_jax_frontend.sh b/scripts/shell/test_jax_frontend.sh index 9a3c0b8a02ded..6b6fbda810259 100755 --- a/scripts/shell/test_jax_frontend.sh +++ b/scripts/shell/test_jax_frontend.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_frontends/test_jax/"$2".py --tb=short +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_frontends/test_jax/"$2".py --tb=short diff --git a/scripts/shell/test_numpy_frontend.sh b/scripts/shell/test_numpy_frontend.sh index 310c671025f8d..67cab85adc997 100755 --- a/scripts/shell/test_numpy_frontend.sh +++ b/scripts/shell/test_numpy_frontend.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_frontends/test_numpy/"$2" --tb=short +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_frontends/test_numpy/"$2" --tb=short diff --git a/scripts/shell/test_tensorflow_frontend.sh b/scripts/shell/test_tensorflow_frontend.sh index 9eee8ee3374cb..848f2477272dc 100755 --- a/scripts/shell/test_tensorflow_frontend.sh +++ b/scripts/shell/test_tensorflow_frontend.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_frontends/test_tensorflow/"$2".py --tb=short +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_frontends/test_tensorflow/"$2".py --tb=short diff --git a/scripts/shell/test_torch_frontend.sh b/scripts/shell/test_torch_frontend.sh index 6dcac9d99eb42..940dbd84bd5d6 100755 --- a/scripts/shell/test_torch_frontend.sh +++ b/scripts/shell/test_torch_frontend.sh @@ -1,2 +1,2 @@ #!/bin/bash -e -docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis unifyai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_frontends/test_torch/"$2".py --tb=short +docker run --rm --env REDIS_URL="$3" --env REDIS_PASSWD="$4" -v `pwd`:/ivy -v `pwd`/.hypothesis:/.hypothesis transpileai/ivy:latest python3 -m pytest --backend "$1" ivy_tests/test_ivy/test_frontends/test_torch/"$2".py --tb=short 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/scripts/update_test_dashboard/update_db.py b/scripts/update_test_dashboard/update_db.py new file mode 100644 index 0000000000000..53783642fecb4 --- /dev/null +++ b/scripts/update_test_dashboard/update_db.py @@ -0,0 +1,55 @@ +import argparse +import json +from pymongo import MongoClient + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="Add all the tests within test_report.json to the remote MongoDB." + ) + parser.add_argument( + "--workflow-link", + type=str, + help="Link to the GitHub actions workflow corresponding to this test.", + ) + parser.add_argument("--db-key", type=str, help="Key for the MongoDB database") + + args = parser.parse_args() + json_report_file = "test_report.json" + + with open(json_report_file, "r") as file: + data = json.load(file) + + tests_data = data.get("tests", None) + + uri = f"mongodb+srv://{args.db_key}@ivytestdashboard.mnzyom5.mongodb.net/?retryWrites=true&w=majority&appName=IvyTestDashboard" + client = MongoClient(uri) + db = client.ivytestdashboard + collection = db["test_results"] + + for test in tests_data: + test_path, test_function_args = test["nodeid"].split("::") + test_path = test_path.replace("ivy_tests/test_ivy/", "") + test_function, test_args = test_function_args.split("[") + test_function = test_function.replace("test_", "") + test_args = test_args.replace("]", "") + test_args = test_args.split("-") + backend = test_args[1] + + if "frontends" in test_path: + test_function = test_function.split("_", 1)[1] + + document = { + "backend": backend, + "function": test_function, + "path": test_path, + "workflow_link": args.workflow_link, + "outcome": test["outcome"], + } + filter_criteria = { + "backend": backend, + "function": test_function, + "path": test_path, + } + + result = collection.replace_one(filter_criteria, document, upsert=True) diff --git a/scripts/update_test_dashboard/update_ivy_core.sh b/scripts/update_test_dashboard/update_ivy_core.sh new file mode 100755 index 0000000000000..7ea88a0c3455a --- /dev/null +++ b/scripts/update_test_dashboard/update_ivy_core.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_functional/test_core/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_ivy_experimental_core.sh b/scripts/update_test_dashboard/update_ivy_experimental_core.sh new file mode 100755 index 0000000000000..2b9560aa1621c --- /dev/null +++ b/scripts/update_test_dashboard/update_ivy_experimental_core.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_functional/test_experimental/test_core/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_ivy_experimental_nn.sh b/scripts/update_test_dashboard/update_ivy_experimental_nn.sh new file mode 100755 index 0000000000000..cc226845cbb87 --- /dev/null +++ b/scripts/update_test_dashboard/update_ivy_experimental_nn.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_functional/test_experimental/test_nn/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_ivy_nn.sh b/scripts/update_test_dashboard/update_ivy_nn.sh new file mode 100755 index 0000000000000..6b631806edb70 --- /dev/null +++ b/scripts/update_test_dashboard/update_ivy_nn.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_functional/test_nn/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_jax_frontends.sh b/scripts/update_test_dashboard/update_jax_frontends.sh new file mode 100755 index 0000000000000..eeb6a57d8543b --- /dev/null +++ b/scripts/update_test_dashboard/update_jax_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_jax/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_jax_lax_frontends.sh b/scripts/update_test_dashboard/update_jax_lax_frontends.sh new file mode 100755 index 0000000000000..a7edf3086be3f --- /dev/null +++ b/scripts/update_test_dashboard/update_jax_lax_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_jax/test_lax/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_jax_nn_frontends.sh b/scripts/update_test_dashboard/update_jax_nn_frontends.sh new file mode 100755 index 0000000000000..761f0bab09e04 --- /dev/null +++ b/scripts/update_test_dashboard/update_jax_nn_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_jax/test_nn/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_jax_numpy_frontends.sh b/scripts/update_test_dashboard/update_jax_numpy_frontends.sh new file mode 100755 index 0000000000000..5717f2830e641 --- /dev/null +++ b/scripts/update_test_dashboard/update_jax_numpy_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_jax/test_numpy/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_numpy_frontends.sh b/scripts/update_test_dashboard/update_numpy_frontends.sh new file mode 100755 index 0000000000000..d00880395c6c0 --- /dev/null +++ b/scripts/update_test_dashboard/update_numpy_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_numpy/test_$submodule/ --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_paddle_frontends.sh b/scripts/update_test_dashboard/update_paddle_frontends.sh new file mode 100755 index 0000000000000..1c90e0449d4b3 --- /dev/null +++ b/scripts/update_test_dashboard/update_paddle_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_paddle/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_tensorflow_frontends.sh b/scripts/update_test_dashboard/update_tensorflow_frontends.sh new file mode 100755 index 0000000000000..6c2f523485128 --- /dev/null +++ b/scripts/update_test_dashboard/update_tensorflow_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_tensorflow/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_tensorflow_keras_frontends.sh b/scripts/update_test_dashboard/update_tensorflow_keras_frontends.sh new file mode 100755 index 0000000000000..34f391a2715eb --- /dev/null +++ b/scripts/update_test_dashboard/update_tensorflow_keras_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_tensorflow/test_keras/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_torch_frontends.sh b/scripts/update_test_dashboard/update_torch_frontends.sh new file mode 100755 index 0000000000000..ffd76336fde7e --- /dev/null +++ b/scripts/update_test_dashboard/update_torch_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_torch/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi diff --git a/scripts/update_test_dashboard/update_torch_nn_functional_frontends.sh b/scripts/update_test_dashboard/update_torch_nn_functional_frontends.sh new file mode 100755 index 0000000000000..e45bbea80f162 --- /dev/null +++ b/scripts/update_test_dashboard/update_torch_nn_functional_frontends.sh @@ -0,0 +1,18 @@ +#!/bin/bash -e + +submodule=$1 +backend=$2 +workflow_link=$3 +db_key=$4 + +set +e +pytest ivy_tests/test_ivy/test_frontends/test_torch/test_nn/test_functional/test_$submodule.py --backend $backend -p no:warnings --tb=short --json-report --json-report-file=test_report.json +pytest_exit_code=$? +set -e + +if [ $pytest_exit_code -eq 0 ] || [ $pytest_exit_code -eq 1 ]; then + python scripts/update_test_dashboard/update_db.py --workflow-link $workflow_link --db-key $db_key + exit 0 +else + exit 1 +fi 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 e98695ecf1b84..5bc9e4bb54213 100644 --- a/setup.py +++ b/setup.py @@ -27,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)) @@ -46,9 +47,10 @@ 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, python_tag, plat_name, options = None, None, None, None if fixed_tag: python_tag, _, plat_name = str(fixed_tag).split("-") @@ -65,15 +67,18 @@ 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( - f"https://github.com/unifyai/binaries/raw/{version}/{search_path}", + f"https://github.com/ivy-llc/binaries/raw/{version}/{search_path}", timeout=40, ) os.makedirs(os.path.dirname(path), exist_ok=True) @@ -110,18 +115,18 @@ def _strip(line): setup( name="ivy", version=__version__, - author="Unify", - author_email="hello@unify.ai", + author="Transpile AI", + author_email="hello@transpile-ai.com", description=( "The unified machine learning framework, enabling framework-agnostic " "functions, layers and libraries." ), long_description=long_description, long_description_content_type="text/markdown", - url="https://unify.ai/ivy", + url="https://ivy.dev", project_urls={ - "Docs": "https://unify.ai/docs/ivy/", - "Source": "https://github.com/unifyai/ivy", + "Docs": "https://ivy.dev/docs/", + "Source": "https://github.com/ivy-llc/ivy", }, include_package_data=True, packages=setuptools.find_packages(), 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"] + } +}