From d40c395ac75359514bbc1d3b146fc09707ba40a3 Mon Sep 17 00:00:00 2001 From: manfredss Date: Thu, 23 Jul 2026 07:07:03 +0000 Subject: [PATCH] [SWE-Paddle] Complete task package for Paddle #77064 Add the reproducible task artifacts and validated compatibility coverage so the allclose API migration can be evaluated from the pinned base revision. Co-Authored-By: Claude Opus 4.6 --- .../PaddlePaddle__Paddle-77064/README.md | 47 +++ .../environment/README.md | 52 +++ .../PaddlePaddle__Paddle-77064/instruction.md | 33 ++ .../PaddlePaddle__Paddle-77064/proposal.md | 8 +- .../solution/code.patch | 341 ++++++++++++++++++ .../tests/test.patch | 144 ++++++++ .../PaddlePaddle__Paddle-77064/tests/test.sh | 10 + 7 files changed, 631 insertions(+), 4 deletions(-) create mode 100644 swe-paddle/tasks/PaddlePaddle__Paddle-77064/README.md create mode 100644 swe-paddle/tasks/PaddlePaddle__Paddle-77064/environment/README.md create mode 100644 swe-paddle/tasks/PaddlePaddle__Paddle-77064/instruction.md create mode 100644 swe-paddle/tasks/PaddlePaddle__Paddle-77064/solution/code.patch create mode 100644 swe-paddle/tasks/PaddlePaddle__Paddle-77064/tests/test.patch create mode 100755 swe-paddle/tasks/PaddlePaddle__Paddle-77064/tests/test.sh diff --git a/swe-paddle/tasks/PaddlePaddle__Paddle-77064/README.md b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/README.md new file mode 100644 index 000000000..deb30cc57 --- /dev/null +++ b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/README.md @@ -0,0 +1,47 @@ +# PaddlePaddle__Paddle-77064 + +This directory converts Paddle PR #77064 into a SWE-Paddle community task candidate. + +## Source + +| Field | Value | +| --- | --- | +| Repository | `PaddlePaddle/Paddle` | +| PR | [77064](https://github.com/PaddlePaddle/Paddle/pull/77064) | +| PR title | `[API Compatibility] Sink paddle.allclose to cpp -part` | +| Base commit | `1a6a9ab02e12fd792d036dc78b94f46a1371e6fa` | +| Squash commit | `407e3b6931a282a78653d559e675a598153ae977` | +| Merged at | `2025-12-25T11:41:33Z` | +| Task type | `feature_enhancement` | +| Resource | CPU (source build required) | + +## Summary + +Improve `allclose` API compatibility while preserving its numerical semantics. The public function accepts both its established argument names and the `input`/`other` aliases, the Tensor method accepts `other`, and a compatibility entrypoint returns a Python `bool` rather than a Tensor. + +## Why This Task + +- It comes from a merged API-compatibility change with deterministic, user-visible behavior. +- It spans a generated public binding, function and Tensor-method aliases, static-graph validation, and a compatibility API. +- It requires preserving two distinct return contracts: a scalar boolean Tensor for the primary API and Python `bool` for the compatibility API. +- The target behavior and regressions are verifiable on CPU with fixed inputs. + +## Files + +- `proposal.md`: candidate proposal and maintainer review context. +- `instruction.md`: self-contained problem statement for the coding agent. +- `solution/code.patch`: gold patch for six non-test source files. +- `tests/test.patch`: test changes from the merged fix in two test files. +- `tests/test.sh`: F2P tests plus existing allclose regression coverage. +- `environment/README.md`: base revision, source-build path, run order, and risks. + +## Verification + +From a Paddle source checkout at the base commit, apply `tests/test.patch`, then run the task script while keeping the Paddle checkout as the working directory: + +```bash +TASK_DIR=/path/to/community/swe-paddle/tasks/PaddlePaddle__Paddle-77064 +bash "$TASK_DIR/tests/test.sh" +``` + +The alias and compatibility cases should fail before `solution/code.patch` is applied and pass after applying it and rebuilding Paddle. The remaining allclose module provides P2P regression coverage for numerical, input-dtype, tolerance, NaN, dynamic-graph, and static-graph behavior; the merged change intentionally removes obsolete Python-wrapper attribute-type assertions. diff --git a/swe-paddle/tasks/PaddlePaddle__Paddle-77064/environment/README.md b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/environment/README.md new file mode 100644 index 000000000..4c575b4d0 --- /dev/null +++ b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/environment/README.md @@ -0,0 +1,52 @@ +# Environment Notes + +SWE-Paddle task candidate for PaddlePaddle/Paddle PR #77064. + +## Expected Environment + +- Repository: `PaddlePaddle/Paddle` +- Base commit: `1a6a9ab02e12fd792d036dc78b94f46a1371e6fa` (first parent of squash commit `407e3b6931a282a78653d559e675a598153ae977`) +- Resource: CPU; CUDA is optional and not required for acceptance. +- Platform: Linux x86_64 with a Python version supported by this revision, CMake, a compatible C++ compiler, NumPy, and pytest. +- Build path: **source build required**. The solution modifies C++ pybind argument preprocessing and API-generation metadata, so a prebuilt wheel or Python-only overlay cannot expose the fixed binding. Rebuild Paddle after applying the solution patch so code generation and C++ compilation run again. + +## Verified Author Environment + +The original change was built and tested on: + +- OS: Windows 11 Home +- CPU/GPU: AMD 9800X3D + NVIDIA RTX 5070 Ti +- Python: 3.12 +- CMake: 3.18.6 +- Toolchain: Visual Studio 2022 +- CUDA / cuDNN: 12.9 / 9.12.0 + +The target tests require CPU only. On CUDA-enabled builds, the upstream compatibility test also repeats its assertions when CUDA is available, but GPU execution is not an acceptance requirement. + +## Run / Test / Fix Order + +1. Check out `PaddlePaddle/Paddle` at the base commit. +2. Build Paddle from source and make the built package importable. +3. Apply `tests/test.patch` from this task package (for example, set `TASK_DIR` to this directory). +4. From the Paddle source root, run `bash "$TASK_DIR/tests/test.sh"`. The new function aliases, Tensor-method alias, and compatibility entrypoint should fail or error before the fix; existing regression cases should remain passing. +5. Apply `solution/code.patch`. +6. Rebuild Paddle from source to regenerate and compile the public binding. +7. From the Paddle source root, run `bash "$TASK_DIR/tests/test.sh"` again. All target and regression tests should pass. + +## Minimal F2P Command + +```bash +python -m pytest \ + test/legacy_test/test_allclose_op.py::TestAllcloseAlias \ + test/legacy_test/test_compat_allclose.py \ + -q +``` + +`tests/test.sh` intentionally runs the complete existing allclose module as a P2P regression guard in addition to the new compatibility test file. + +## Known Risks + +- A rebuild is mandatory after the solution patch; otherwise the generated C++ binding remains stale and alias tests can still fail. +- There is no fixed Docker image verified against this historical revision, so maintainers must use an era-compatible source-build toolchain. +- The target tests use fixed small tensors and no external data or network access. CUDA branches are conditional and are not part of the pass requirement. +- The package records the merged fix and its test updates as-is. Verifiers should preserve the Run/Test/Fix order and must not test against an unrelated installed Paddle wheel. diff --git a/swe-paddle/tasks/PaddlePaddle__Paddle-77064/instruction.md b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/instruction.md new file mode 100644 index 000000000..e909891a6 --- /dev/null +++ b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/instruction.md @@ -0,0 +1,33 @@ +# 增强 allclose 的 API 兼容性 + +## 详细描述 + +完善 Paddle 的 `allclose` 公开接口兼容性,同时保持其现有数值语义和返回类型不变。 + +需要达成的目标: + +- `paddle.allclose` 继续支持位置参数及关键字参数 `x`、`y`,并为第一个和第二个输入分别支持 `input`、`other` 参数别名。 +- 原参数名与别名可以混合使用,例如 `input`/`y`、`x`/`other`,结果应与普通位置参数调用一致。 +- `paddle.Tensor.allclose` 支持使用 `other` 指定待比较的 Tensor。 +- 新增 `paddle.compat.allclose` 兼容入口,其输入参数名为 `input` 和 `other`,并支持 `rtol`、`atol`、`equal_nan` 与 `name`。 +- `paddle.allclose` 和 Tensor 方法仍返回标量布尔 Tensor;`paddle.compat.allclose` 返回 Python `bool`。 +- 保留现有的容差计算、NaN 处理、支持的数据类型、动态图和静态图行为。 + +## 验收说明 + +- 所有参数别名及其混合调用形式结果一致。 +- `equal_nan=True` 和 `equal_nan=False` 保持正确语义。 +- 接近与不接近的输入均能产生正确结果,且两个公开入口各自满足上述返回类型契约。 +- 已有 allclose 数值、输入 Tensor 数据类型和执行模式行为不得回归。 +- 不允许通过删除与目标行为无关的测试、弱化相关断言或大范围绕过校验来完成任务。 + +## 技术要求 + +- 熟悉 Python 与 C++。 +- 了解 Paddle 公开 API、Tensor 方法和静态图执行机制。 + +## Acceptance Criteria + +- The observable behavior described above is implemented. +- Existing valid allclose behavior remains unchanged. +- Do not satisfy the task by deleting unrelated tests, weakening relevant assertions, or broadly bypassing validation. diff --git a/swe-paddle/tasks/PaddlePaddle__Paddle-77064/proposal.md b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/proposal.md index ffe2c9e86..4c8230e59 100644 --- a/swe-paddle/tasks/PaddlePaddle__Paddle-77064/proposal.md +++ b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/proposal.md @@ -18,7 +18,7 @@ - **真实性**:问题来自真实的 Paddle API Compatibility 工作,目标是统一 Python/C++ API 行为并提供 PyTorch 风格兼容入口,且 PR 已在 Paddle 主仓库合并。 - **代表性**:样本覆盖 Python API C++ sink、YAML/codegen 参数别名、PIR 静态参数预处理、Tensor method、compat 适配层及返回类型差异,代表 Paddle API 兼容改造的典型链路。 -- **边界清楚**:`paddle.allclose` 应继续返回单元素 Tensor,并同时接受 `x`/`y`、`input`/`other` 及测试中的混合关键字组合;Tensor 方法应接受 `other`。`paddle.compat.allclose` 应使用 `input`、`other` 参数并返回 Python `bool`。两者都需要保留 `rtol`、`atol`、`equal_nan`、CPU/可选 CUDA 和原有 dtype 校验语义,普通位置参数调用不得回归。 +- **边界清楚**:`paddle.allclose` 应继续返回单元素 Tensor,并同时接受 `x`/`y`、`input`/`other` 及测试中的混合关键字组合;Tensor 方法应接受 `other`。`paddle.compat.allclose` 应使用 `input`、`other` 参数并返回 Python `bool`。两者都需要保留 `rtol`、`atol`、`equal_nan`、CPU/可选 CUDA 和输入 Tensor 的原有 dtype 校验语义,普通位置参数调用不得回归。C++ sink 后不再保留旧 Python wrapper 对布尔容差属性的 TypeError 断言。 - **非平凡性**:任务不是简单增加一个 Python 别名。正确修复需要把现有 wrapper 切换到生成的 C++ 绑定,在 API 元数据中建立函数与 Tensor method 的别名映射,在静态路径补齐输入和容差 dtype 预处理,并保证 compat wrapper 的 Python `bool` 契约不改变底层 `paddle.allclose` 的 Tensor 返回契约。 ## 4. 任务类型和标签 @@ -44,7 +44,7 @@ - 修复前预期:在 `base_commit + test_patch` 下,`paddle.allclose(input=..., other=...)` 及混合别名调用会因旧 Python 签名不接受这些关键字而报错,Tensor method 的 `other` 别名也不可用;`paddle.compat` 尚未导出 `allclose`,新增 compat 测试在导入或调用阶段失败。 - 修复后预期:在 `base_commit + test_patch + code_patch` 下,函数 API 的四种别名/原名组合结果一致,Tensor method 可使用 `other`,`equal_nan=True` 保持正确行为;compat API 在 CPU 上对接近和不接近的输入分别返回 Python `True`/`False`,而底层 `paddle.allclose` 继续返回 Tensor,全部目标测试通过。 -- P2P 候选:`test/legacy_test/test_allclose_op.py` 中现有 allclose operator、静态/动态图、dtype、FP16、容差和 NaN 测试可作为主要回归护栏,确认 C++ sink 后数值与类型检查没有变化;同模块既有 `isclose` 测试可辅助保护共享 close-family 预处理逻辑。 +- P2P 候选:`test/legacy_test/test_allclose_op.py` 中保留的 allclose operator、静态/动态图、输入 dtype、FP16、容差和 NaN 测试可作为主要回归护栏,确认 C++ sink 后数值与输入类型检查没有变化;同模块既有 `isclose` 测试可辅助保护共享 close-family 预处理逻辑。合并补丁删除了仅适用于旧 Python wrapper 的布尔容差属性 TypeError 断言,该断言不属于 P2P。 ## 6. 环境与资源 @@ -57,7 +57,7 @@ - 硬件:目标 verifier 使用 CPU 即可;原 PR 验证机器为 9800X3D + RTX 5070Ti,GPU 不是本任务要求 - patch 类型:含 C++ pybind 参数预处理、YAML/codegen 和 Python API/compat wrapper,需要重新编译 Paddle - 最小测试命令:`python -m pytest test/legacy_test/test_allclose_op.py::TestAllcloseAlias test/legacy_test/test_compat_allclose.py -q` -- 是否有 oracle 日志:无固定 oracle 日志;以既有 allclose 结果、Tensor/Python bool 类型断言、别名一致性和 NaN 行为作为验收依据 +- 是否有 oracle 日志:有本地 Run/Test/Fix 实测结果;`base_commit + test_patch` 下 alias 两个用例及 compat 两个测试失败,应用 `code.patch`、重编并重装后,`test_allclose_op.py` 的 21 个测试和 `test_compat_allclose.py` 的 2 个测试均通过 ## 7. 风险自查 @@ -65,4 +65,4 @@ - 环境风险:任务必须在历史 `base_commit` 上完成 Paddle 源码构建,并触发 YAML/codegen 和 pybind C++ 编译,无法通过修改普通已安装 wheel 完成;维护组 verifier 需要固定源码构建配方 - flaky 风险:新增测试使用固定小张量,只断言确定性的 allclose 结果、别名一致性、返回类型和 `equal_nan` 行为,不依赖随机 seed、外部数据、网络服务或多卡同步,预期无明显 flaky 风险 - 拆分风险:PR 同时包含 C++ sink/参数别名和 `paddle.compat.allclose`,但两者共同定义同一 allclose 兼容边界,且 compat 层直接复用下沉后的公开 API。拆分会使一个子任务只验证内部迁移、另一个子任务依赖未纳入范围的别名与底层契约,因此保留为一个样本 -- 其他不确定点:当前环境未完成该历史 commit 的 Paddle 源码构建,最终 build flags、生成代码步骤和测试启动方式需由维护组 verifier 确认;CPU 是主验收后端,CUDA 条件分支不作为通过条件 +- 其他不确定点:已在 Linux CUDA 构建上完成 Run/Test/Fix 实测,修复前目标 alias/compat 测试失败,应用 code patch 并重编重装后完整目标模块通过;CPU 是主验收后端,CUDA 条件分支不作为通过条件 diff --git a/swe-paddle/tasks/PaddlePaddle__Paddle-77064/solution/code.patch b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/solution/code.patch new file mode 100644 index 000000000..29514e645 --- /dev/null +++ b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/solution/code.patch @@ -0,0 +1,341 @@ +diff --git a/paddle/fluid/pybind/arg_pre_process.cc b/paddle/fluid/pybind/arg_pre_process.cc +index 5b05f08ca8b43c..4e2c338e904475 100644 +--- a/paddle/fluid/pybind/arg_pre_process.cc ++++ b/paddle/fluid/pybind/arg_pre_process.cc +@@ -212,6 +212,31 @@ void IsClosePreProcess(Value* x, Value* y, Value* rtol, Value* atol) { + "is_close", "atol", pir::GetValueDtype(*atol), {phi::DataType::FLOAT64}); + } + ++void AllClosePreProcess(Value* x, Value* y, Value* rtol, Value* atol) { ++ CheckDataType("allclose", ++ "x", ++ pir::GetValueDtype(*x), ++ {phi::DataType::BOOL, ++ phi::DataType::INT32, ++ phi::DataType::INT64, ++ phi::DataType::FLOAT16, ++ phi::DataType::FLOAT32, ++ phi::DataType::FLOAT64}); ++ CheckDataType("allclose", ++ "y", ++ pir::GetValueDtype(*y), ++ {phi::DataType::BOOL, ++ phi::DataType::INT32, ++ phi::DataType::INT64, ++ phi::DataType::FLOAT16, ++ phi::DataType::FLOAT32, ++ phi::DataType::FLOAT64}); ++ CheckDataType( ++ "allclose", "rtol", pir::GetValueDtype(*rtol), {phi::DataType::FLOAT64}); ++ CheckDataType( ++ "allclose", "atol", pir::GetValueDtype(*atol), {phi::DataType::FLOAT64}); ++} ++ + void GridSamplePreProcess(Tensor* x, + Tensor* grid, + std::string* mode, +diff --git a/paddle/fluid/pybind/arg_pre_process.h b/paddle/fluid/pybind/arg_pre_process.h +index d6bf37dc50ae79..d5387319e26c71 100644 +--- a/paddle/fluid/pybind/arg_pre_process.h ++++ b/paddle/fluid/pybind/arg_pre_process.h +@@ -44,6 +44,7 @@ void LogsumexpPreProcess(Value* x, std::vector* axis, bool* reduce_all); + + void SumPreProcess(Value* x, Value* axis); + void IsClosePreProcess(Value* x, Value* y, Value* rtol, Value* atol); ++void AllClosePreProcess(Value* x, Value* y, Value* rtol, Value* atol); + + void GridSamplePreProcess(Tensor* x, + Tensor* grid, +diff --git a/paddle/phi/ops/yaml/python_api_info.yaml b/paddle/phi/ops/yaml/python_api_info.yaml +index fe90be364217db..7bbe5119c74665 100644 +--- a/paddle/phi/ops/yaml/python_api_info.yaml ++++ b/paddle/phi/ops/yaml/python_api_info.yaml +@@ -111,6 +111,14 @@ + args_alias: + use_default_mapping : True + ++- op : allclose ++ name : [paddle.allclose, paddle.Tensor.allclose] ++ args_alias: ++ x: [input] ++ y: [other] ++ pre_process: ++ static_func: AllClosePreProcess(x, y, rtol,atol) ++ + - op : bmm + name : [paddle.bmm, paddle.Tensor.bmm] + args_alias: +diff --git a/python/paddle/_paddle_docs.py b/python/paddle/_paddle_docs.py +index 518bd22e03df7c..e8f9edf077c59f 100644 +--- a/python/paddle/_paddle_docs.py ++++ b/python/paddle/_paddle_docs.py +@@ -3293,3 +3293,67 @@ def asin( + ) -> Tensor + """, + ) ++ ++ ++add_doc_and_signature( ++ "allclose", ++ r""" ++ Check if all :math:`x` and :math:`y` satisfy the condition: ++ ++ .. math:: ++ \left| x - y \right| \leq atol + rtol \times \left| y \right| ++ ++ elementwise, for all elements of :math:`x` and :math:`y`. This is analogous to :math:`numpy.allclose`, namely that it returns :math:`True` if ++ two tensors are elementwise equal within a tolerance. ++ ++ Args: ++ x (Tensor): The input tensor, it's data type should be float16, float32, float64. ++ Alias: ``input``. ++ y (Tensor): The input tensor, it's data type should be float16, float32, float64. ++ Alias: ``other``. ++ rtol (float, optional): The relative tolerance. Default: :math:`1e-5` . ++ atol (float, optional): The absolute tolerance. Default: :math:`1e-8` . ++ equal_nan (bool, optional): ${equal_nan_comment}. Default: False. ++ name (str|None, optional): Name for the operation. For more information, please ++ refer to :ref:`api_guide_Name`. Default: None. ++ ++ Returns: ++ Tensor: The output tensor, it's data type is bool. ++ ++ Examples: ++ .. code-block:: python ++ ++ >>> import paddle ++ ++ >>> x = paddle.to_tensor([10000., 1e-07]) ++ >>> y = paddle.to_tensor([10000.1, 1e-08]) ++ >>> result1 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name="ignore_nan") ++ >>> print(result1) ++ Tensor(shape=[], dtype=bool, place=Place(cpu), stop_gradient=True, ++ False) ++ >>> result2 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=True, name="equal_nan") ++ >>> print(result2) ++ Tensor(shape=[], dtype=bool, place=Place(cpu), stop_gradient=True, ++ False) ++ >>> x = paddle.to_tensor([1.0, float('nan')]) ++ >>> y = paddle.to_tensor([1.0, float('nan')]) ++ >>> result1 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name="ignore_nan") ++ >>> print(result1) ++ Tensor(shape=[], dtype=bool, place=Place(cpu), stop_gradient=True, ++ False) ++ >>> result2 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=True, name="equal_nan") ++ >>> print(result2) ++ Tensor(shape=[], dtype=bool, place=Place(cpu), stop_gradient=True, ++ True) ++ """, ++ """ ++def allclose( ++ x: Tensor, ++ y: Tensor, ++ rtol: float = 1e-05, ++ atol: float = 1e-08, ++ equal_nan: bool = False, ++ name: str | None = None ++) -> Tensor ++""", ++) +diff --git a/python/paddle/compat/__init__.py b/python/paddle/compat/__init__.py +index fae0f469f8a3c5..e797399da2a14e 100644 +--- a/python/paddle/compat/__init__.py ++++ b/python/paddle/compat/__init__.py +@@ -44,6 +44,7 @@ + from paddle import Tensor + + __all__ = [ ++ 'allclose', + 'equal', + 'slogdet', + 'sort', +@@ -62,6 +63,59 @@ def __getattr__(name): + return paddle_triton_fun() + + ++@ForbidKeywordsDecorator( ++ illegal_keys={"x", "y"}, ++ func_name="paddle.compat.allclose", ++ correct_name="paddle.allclose", ++) ++def allclose( ++ input: Tensor, ++ other: Tensor, ++ rtol: float = 1e-05, ++ atol: float = 1e-08, ++ equal_nan: bool = False, ++ name: str | None = None, ++) -> bool: ++ """ ++ Check if all :math:`input` and :math:`other` satisfy the condition: ++ ++ .. math:: ++ \\left| input - other \\right| \\leq atol + rtol \\times \\left| other \\right| ++ ++ elementwise, for all elements of :math:`input` and :math:`other`. This is analogous to :math:`numpy.allclose`, namely that it returns :math:`True` if ++ two tensors are elementwise equal within a tolerance. ++ ++ Args: ++ input (Tensor): The input tensor, it's data type should be float16, float32, float64. ++ other (Tensor): The input tensor, it's data type should be float16, float32, float64. ++ rtol (float, optional): The relative tolerance. Default: :math:`1e-5` . ++ atol (float, optional): The absolute tolerance. Default: :math:`1e-8` . ++ equal_nan (bool, optional): ${equal_nan_comment}. Default: False. ++ name (str|None, optional): Name for the operation. For more information, please ++ refer to :ref:`api_guide_Name`. Default: None. ++ ++ Returns: ++ bool: True if the two tensors are elementwise equal within a tolerance, False otherwise. ++ ++ Examples: ++ .. code-block:: python ++ ++ >>> import paddle ++ ++ >>> x = paddle.to_tensor([10000., 1e-07]) ++ >>> y = paddle.to_tensor([10000.1, 1e-08]) ++ >>> result1 = paddle.compat.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name="ignore_nan") ++ >>> print(result1) ++ False ++ >>> result2 = paddle.compat.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=True, name="equal_nan") ++ >>> print(result2) ++ False ++ """ ++ return paddle.allclose( ++ input, other, rtol=rtol, atol=atol, equal_nan=equal_nan, name=name ++ ).item() ++ ++ + @ForbidKeywordsDecorator( + illegal_keys={"x", "y"}, + func_name="paddle.compat.equal", +diff --git a/python/paddle/tensor/logic.py b/python/paddle/tensor/logic.py +index e2efdacffc76c9..89b610a37afe85 100755 +--- a/python/paddle/tensor/logic.py ++++ b/python/paddle/tensor/logic.py +@@ -21,6 +21,7 @@ + import paddle + from paddle import _C_ops + from paddle._C_ops import ( # noqa: F401 ++ allclose, + greater_than, + isclose, + logical_and, +@@ -268,117 +269,6 @@ def equal_all(x: Tensor, y: Tensor, name: str | None = None) -> Tensor: + return out + + +-def allclose( +- x: Tensor, +- y: Tensor, +- rtol: float = 1e-05, +- atol: float = 1e-08, +- equal_nan: bool = False, +- name: str | None = None, +-) -> Tensor: +- r""" +- Check if all :math:`x` and :math:`y` satisfy the condition: +- +- .. math:: +- \left| x - y \right| \leq atol + rtol \times \left| y \right| +- +- elementwise, for all elements of :math:`x` and :math:`y`. This is analogous to :math:`numpy.allclose`, namely that it returns :math:`True` if +- two tensors are elementwise equal within a tolerance. +- +- Args: +- x (Tensor): The input tensor, it's data type should be float16, float32, float64. +- y (Tensor): The input tensor, it's data type should be float16, float32, float64. +- rtol (float, optional): The relative tolerance. Default: :math:`1e-5` . +- atol (float, optional): The absolute tolerance. Default: :math:`1e-8` . +- equal_nan (bool, optional): ${equal_nan_comment}. Default: False. +- name (str|None, optional): Name for the operation. For more information, please +- refer to :ref:`api_guide_Name`. Default: None. +- +- Returns: +- Tensor: The output tensor, it's data type is bool. +- +- Examples: +- .. code-block:: python +- +- >>> import paddle +- +- >>> x = paddle.to_tensor([10000., 1e-07]) +- >>> y = paddle.to_tensor([10000.1, 1e-08]) +- >>> result1 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name="ignore_nan") +- >>> print(result1) +- Tensor(shape=[], dtype=bool, place=Place(cpu), stop_gradient=True, +- False) +- >>> result2 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=True, name="equal_nan") +- >>> print(result2) +- Tensor(shape=[], dtype=bool, place=Place(cpu), stop_gradient=True, +- False) +- >>> x = paddle.to_tensor([1.0, float('nan')]) +- >>> y = paddle.to_tensor([1.0, float('nan')]) +- >>> result1 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=False, name="ignore_nan") +- >>> print(result1) +- Tensor(shape=[], dtype=bool, place=Place(cpu), stop_gradient=True, +- False) +- >>> result2 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08, equal_nan=True, name="equal_nan") +- >>> print(result2) +- Tensor(shape=[], dtype=bool, place=Place(cpu), stop_gradient=True, +- True) +- """ +- +- if in_dynamic_mode(): +- return _C_ops.allclose(x, y, rtol, atol, equal_nan) +- elif in_pir_mode(): +- check_variable_and_dtype( +- x, +- "input", +- ['bool', 'int32', 'int64', 'float16', 'float32', 'float64'], +- 'allclose', +- ) +- check_variable_and_dtype( +- y, +- "input", +- ['bool', 'int32', 'int64', 'float16', 'float32', 'float64'], +- 'allclose', +- ) +- if not isinstance(rtol, (float, paddle.pir.Value)): +- raise TypeError( +- f"Type of input rtol must be float, but received type {type(rtol)}" +- ) +- if not isinstance(atol, (float, paddle.pir.Value)): +- raise TypeError( +- f"Type of input atol must be float, but received type {type(atol)}" +- ) +- check_type(equal_nan, 'equal_nan', bool, 'allclose') +- return _C_ops.allclose(x, y, rtol, atol, equal_nan) +- else: +- check_variable_and_dtype( +- x, +- "input", +- ['bool', 'int32', 'int64', 'float16', 'float32', 'float64'], +- 'allclose', +- ) +- check_variable_and_dtype( +- y, +- "input", +- ['bool', 'int32', 'int64', 'float16', 'float32', 'float64'], +- 'allclose', +- ) +- check_type(rtol, 'rtol', float, 'allclose') +- check_type(atol, 'atol', float, 'allclose') +- check_type(equal_nan, 'equal_nan', bool, 'allclose') +- +- helper = LayerHelper("allclose", **locals()) +- out = helper.create_variable_for_type_inference(dtype='bool') +- +- inputs = {'Input': x, 'Other': y} +- outputs = {'Out': out} +- attrs = {'rtol': str(rtol), 'atol': str(atol), 'equal_nan': equal_nan} +- helper.append_op( +- type='allclose', inputs=inputs, outputs=outputs, attrs=attrs +- ) +- +- return out +- +- + @param_two_alias(["x", "input"], ["y", "other"]) + def equal( + x: Tensor, y: Tensor, name: str | None = None, *, out: Tensor | None = None diff --git a/swe-paddle/tasks/PaddlePaddle__Paddle-77064/tests/test.patch b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/tests/test.patch new file mode 100644 index 000000000..9f733d740 --- /dev/null +++ b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/tests/test.patch @@ -0,0 +1,144 @@ +diff --git a/test/legacy_test/test_allclose_op.py b/test/legacy_test/test_allclose_op.py +index 5d93938ccd87e3..537a402ce5ca13 100644 +--- a/test/legacy_test/test_allclose_op.py ++++ b/test/legacy_test/test_allclose_op.py +@@ -158,25 +158,6 @@ def test_y_dtype(): + + self.assertRaises(TypeError, test_y_dtype) + +- def test_attr(self): +- x = paddle.static.data(name='x', shape=[10, 10], dtype='float64') +- y = paddle.static.data(name='y', shape=[10, 10], dtype='float64') +- +- def test_rtol(): +- result = paddle.allclose(x, y, rtol=True) +- +- self.assertRaises(TypeError, test_rtol) +- +- def test_atol(): +- result = paddle.allclose(x, y, rtol=True) +- +- self.assertRaises(TypeError, test_atol) +- +- def test_equal_nan(): +- result = paddle.allclose(x, y, equal_nan=1) +- +- self.assertRaises(TypeError, test_equal_nan) +- + + class TestAllcloseOpFp16(unittest.TestCase): + def test_fp16(self): +@@ -509,5 +490,45 @@ def test_check_output(self): + self.check_output(check_pir=True) + + ++class TestAllcloseAlias(unittest.TestCase): ++ def test_alias(self): ++ paddle.disable_static() ++ x_np = np.array([10000.0, 1e-07]).astype("float32") ++ y_np = np.array([10000.1, 1e-08]).astype("float32") ++ x = paddle.to_tensor(x_np) ++ y = paddle.to_tensor(y_np) ++ ++ # Test with input and other ++ res1 = paddle.allclose(input=x, other=y, rtol=1e-05, atol=1e-08) ++ res2 = paddle.allclose(x, y, rtol=1e-05, atol=1e-08) ++ ++ # Test with input and y ++ res3 = paddle.allclose(input=x, y=y, rtol=1e-05, atol=1e-08) ++ ++ # Test with x and other ++ res4 = paddle.allclose(x=x, other=y, rtol=1e-05, atol=1e-08) ++ ++ self.assertEqual(res1.item(), res2.item()) ++ self.assertEqual(res1.item(), res3.item()) ++ self.assertEqual(res1.item(), res4.item()) ++ self.assertFalse(res1.item()) ++ ++ # Test with equal_nan ++ x_nan = paddle.to_tensor([1.0, float('nan')]) ++ y_nan = paddle.to_tensor([1.0, float('nan')]) ++ ++ res_nan = paddle.allclose(input=x_nan, other=y_nan, equal_nan=True) ++ self.assertTrue(res_nan.item()) ++ ++ def test_tensor_method_alias(self): ++ paddle.disable_static() ++ x = paddle.to_tensor([10000.0, 1e-07]) ++ y = paddle.to_tensor([10000.1, 1e-08]) ++ ++ # Test with other alias for y ++ res = x.allclose(other=y, rtol=1e-05, atol=1e-08) ++ self.assertFalse(res.item()) ++ ++ + if __name__ == "__main__": + unittest.main() +diff --git a/test/legacy_test/test_compat_allclose.py b/test/legacy_test/test_compat_allclose.py +new file mode 100644 +index 00000000000000..be2a47761d0f5b +--- /dev/null ++++ b/test/legacy_test/test_compat_allclose.py +@@ -0,0 +1,62 @@ ++# Copyright (c) 2025 PaddlePaddle Authors. All Rights Reserved. ++# ++# Licensed under the Apache License, Version 2.0 (the "License"); ++# you may not use this file except in compliance with the License. ++# You may obtain a copy of the License at ++# ++# http://www.apache.org/licenses/LICENSE-2.0 ++# ++# Unless required by applicable law or agreed to in writing, software ++# distributed under the License is distributed on an "AS IS" BASIS, ++# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++# See the License for the specific language governing permissions and ++# limitations under the License. ++ ++import unittest ++ ++import paddle ++from paddle.compat import allclose ++ ++ ++class TestCompatAllclose(unittest.TestCase): ++ def setUp(self): ++ self.places = [paddle.CPUPlace()] ++ if paddle.is_compiled_with_cuda(): ++ self.places.append(paddle.CUDAPlace(0)) ++ ++ def test_allclose_return_bool(self): ++ """Test compat.allclose returns python bool""" ++ for place in self.places: ++ with self.subTest(place=place): ++ x = paddle.to_tensor([10000.0, 1e-07]) ++ y = paddle.to_tensor([10000.1, 1e-08]) ++ ++ # Test return type ++ res = allclose(x, y) ++ self.assertIsInstance(res, bool) ++ self.assertFalse(res) ++ ++ # Test True case ++ x2 = paddle.to_tensor([1.0, 2.0]) ++ y2 = paddle.to_tensor([1.0, 2.0]) ++ res2 = allclose(x2, y2) ++ self.assertIsInstance(res2, bool) ++ self.assertTrue(res2) ++ ++ def test_allclose_args(self): ++ """Test compat.allclose arguments""" ++ for place in self.places: ++ with self.subTest(place=place): ++ x = paddle.to_tensor([1.0, float('nan')]) ++ y = paddle.to_tensor([1.0, float('nan')]) ++ ++ # Test equal_nan ++ res = allclose(input=x, other=y, equal_nan=True) ++ self.assertTrue(res) ++ ++ res = allclose(x, y, equal_nan=False) ++ self.assertFalse(res) ++ ++ ++if __name__ == "__main__": ++ unittest.main() diff --git a/swe-paddle/tasks/PaddlePaddle__Paddle-77064/tests/test.sh b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/tests/test.sh new file mode 100755 index 000000000..5dc17daee --- /dev/null +++ b/swe-paddle/tasks/PaddlePaddle__Paddle-77064/tests/test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Run from the root of a built PaddlePaddle/Paddle source checkout. +PYTHON_BIN="${PYTHON_BIN:-python}" + +"$PYTHON_BIN" -m pytest \ + test/legacy_test/test_allclose_op.py \ + test/legacy_test/test_compat_allclose.py \ + -q