217 lines
7.7 KiB
Python
217 lines
7.7 KiB
Python
# Copyright (c) 2026 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.
|
|
|
|
"""
|
|
复数张量操作单元测试 / Complex Tensor Operations Unit Tests
|
|
|
|
测试目标 / Test Target:
|
|
paddle复数张量操作 (覆盖率较低)
|
|
|
|
覆盖的模块 / Covered Modules:
|
|
- paddle.complex: 创建复数张量
|
|
- paddle.real: 获取实部
|
|
- paddle.imag: 获取虚部
|
|
- paddle.angle: 获取相位角
|
|
- paddle.conj: 共轭
|
|
- paddle.as_complex: 转换为复数
|
|
- paddle.as_real: 转换为实数
|
|
|
|
作用 / Purpose:
|
|
覆盖复数张量操作的各种代码路径,提高复数运算的测试覆盖率。
|
|
"""
|
|
|
|
import unittest
|
|
|
|
import numpy as np
|
|
|
|
import paddle
|
|
|
|
paddle.disable_static()
|
|
|
|
|
|
class TestComplexCreation(unittest.TestCase):
|
|
"""测试复数张量创建 / Test complex tensor creation"""
|
|
|
|
def test_complex_basic(self):
|
|
"""测试基本复数张量创建 / Test basic complex tensor creation"""
|
|
real = paddle.to_tensor([1.0, 2.0, 3.0])
|
|
imag = paddle.to_tensor([4.0, 5.0, 6.0])
|
|
z = paddle.complex(real, imag)
|
|
self.assertEqual(z.dtype, paddle.complex64)
|
|
self.assertEqual(z.shape, [3])
|
|
|
|
def test_complex_from_numpy(self):
|
|
"""测试从numpy创建复数张量 / Test complex tensor from numpy"""
|
|
np_z = np.array([1 + 2j, 3 + 4j], dtype=np.complex64)
|
|
z = paddle.to_tensor(np_z)
|
|
self.assertEqual(z.dtype, paddle.complex64)
|
|
|
|
def test_complex128(self):
|
|
"""测试complex128类型 / Test complex128 type"""
|
|
real = paddle.to_tensor([1.0, 2.0], dtype='float64')
|
|
imag = paddle.to_tensor([3.0, 4.0], dtype='float64')
|
|
z = paddle.complex(real, imag)
|
|
self.assertEqual(z.dtype, paddle.complex128)
|
|
|
|
def test_complex_2d(self):
|
|
"""测试2D复数张量 / Test 2D complex tensor"""
|
|
real = paddle.randn([3, 4])
|
|
imag = paddle.randn([3, 4])
|
|
z = paddle.complex(real, imag)
|
|
self.assertEqual(z.shape, [3, 4])
|
|
|
|
|
|
class TestComplexDecomposition(unittest.TestCase):
|
|
"""测试复数分解操作 / Test complex decomposition"""
|
|
|
|
def setUp(self):
|
|
"""初始化复数张量 / Initialize complex tensor"""
|
|
self.real = paddle.to_tensor([1.0, 2.0, 3.0])
|
|
self.imag = paddle.to_tensor([4.0, 5.0, 6.0])
|
|
self.z = paddle.complex(self.real, self.imag)
|
|
|
|
def test_real_part(self):
|
|
"""测试获取实部 / Test getting real part"""
|
|
real = paddle.real(self.z)
|
|
np.testing.assert_allclose(real.numpy(), self.real.numpy())
|
|
|
|
def test_imag_part(self):
|
|
"""测试获取虚部 / Test getting imaginary part"""
|
|
imag = paddle.imag(self.z)
|
|
np.testing.assert_allclose(imag.numpy(), self.imag.numpy())
|
|
|
|
def test_angle(self):
|
|
"""测试相位角 / Test angle (phase)"""
|
|
# angle(1+1j) = pi/4
|
|
z = paddle.to_tensor([1.0 + 1.0j])
|
|
angle = paddle.angle(z)
|
|
self.assertAlmostEqual(float(angle.item()), np.pi / 4, places=5)
|
|
|
|
def test_abs_complex(self):
|
|
"""测试复数模 / Test complex absolute value"""
|
|
# |3 + 4j| = 5
|
|
z = paddle.to_tensor([3.0 + 4.0j])
|
|
magnitude = paddle.abs(z)
|
|
self.assertAlmostEqual(float(magnitude.item()), 5.0, places=4)
|
|
|
|
def test_conj(self):
|
|
"""测试共轭 / Test conjugate"""
|
|
conj = paddle.conj(self.z)
|
|
# Real part same, imaginary part negated
|
|
np.testing.assert_allclose(paddle.real(conj).numpy(), self.real.numpy())
|
|
np.testing.assert_allclose(
|
|
paddle.imag(conj).numpy(), -self.imag.numpy()
|
|
)
|
|
|
|
|
|
class TestAsComplexReal(unittest.TestCase):
|
|
"""测试as_complex和as_real转换 / Test as_complex and as_real conversion"""
|
|
|
|
def test_as_complex(self):
|
|
"""测试as_complex转换 / Test as_complex conversion"""
|
|
x = paddle.randn([3, 2]) # Last dim must be 2
|
|
z = paddle.as_complex(x)
|
|
self.assertEqual(z.shape, [3])
|
|
self.assertTrue(z.dtype in [paddle.complex64, paddle.complex128])
|
|
|
|
def test_as_real(self):
|
|
"""测试as_real转换 / Test as_real conversion"""
|
|
real = paddle.randn([3, 4])
|
|
imag = paddle.randn([3, 4])
|
|
z = paddle.complex(real, imag)
|
|
x = paddle.as_real(z)
|
|
# Last dim should be 2 (real, imag)
|
|
self.assertEqual(x.shape, [3, 4, 2])
|
|
|
|
def test_as_complex_as_real_roundtrip(self):
|
|
"""测试as_complex和as_real的往返转换 / Test as_complex/as_real roundtrip"""
|
|
x = paddle.randn([3, 2])
|
|
z = paddle.as_complex(x)
|
|
x_recovered = paddle.as_real(z)
|
|
np.testing.assert_allclose(x.numpy(), x_recovered.numpy(), rtol=1e-5)
|
|
|
|
|
|
class TestComplexArithmetic(unittest.TestCase):
|
|
"""测试复数算术运算 / Test complex arithmetic"""
|
|
|
|
def test_complex_add(self):
|
|
"""测试复数加法 / Test complex addition"""
|
|
z1 = paddle.to_tensor([1.0 + 2.0j, 3.0 + 4.0j])
|
|
z2 = paddle.to_tensor([1.0 + 1.0j, 1.0 + 1.0j])
|
|
result = z1 + z2
|
|
expected = np.array([2.0 + 3.0j, 4.0 + 5.0j])
|
|
np.testing.assert_allclose(result.numpy(), expected, rtol=1e-5)
|
|
|
|
def test_complex_multiply(self):
|
|
"""测试复数乘法 / Test complex multiplication"""
|
|
z1 = paddle.to_tensor([1.0 + 1.0j])
|
|
z2 = paddle.to_tensor([1.0 + 1.0j])
|
|
result = z1 * z2
|
|
# (1+i)*(1+i) = 1 + 2i - 1 = 2i
|
|
expected = np.array([0.0 + 2.0j])
|
|
np.testing.assert_allclose(result.numpy(), expected, atol=1e-5)
|
|
|
|
def test_complex_matmul(self):
|
|
"""测试复数矩阵乘法 / Test complex matrix multiplication"""
|
|
real = paddle.randn([3, 4])
|
|
imag = paddle.randn([3, 4])
|
|
z = paddle.complex(real, imag)
|
|
real2 = paddle.randn([4, 5])
|
|
imag2 = paddle.randn([4, 5])
|
|
z2 = paddle.complex(real2, imag2)
|
|
result = paddle.matmul(z, z2)
|
|
self.assertEqual(result.shape, [3, 5])
|
|
|
|
def test_complex_exp(self):
|
|
"""测试复数指数函数 / Test complex exponential"""
|
|
# e^(i*pi) ≈ -1
|
|
z = paddle.to_tensor([1j * np.pi], dtype='complex64')
|
|
result = paddle.exp(z)
|
|
self.assertAlmostEqual(
|
|
float(paddle.real(result).numpy()[0]), -1.0, places=4
|
|
)
|
|
|
|
def test_complex_sum(self):
|
|
"""测试复数求和 / Test complex sum"""
|
|
z = paddle.to_tensor([1.0 + 2.0j, 3.0 + 4.0j])
|
|
result = z.sum()
|
|
self.assertAlmostEqual(
|
|
float(paddle.real(result).numpy()), 4.0, places=5
|
|
)
|
|
self.assertAlmostEqual(
|
|
float(paddle.imag(result).numpy()), 6.0, places=5
|
|
)
|
|
|
|
|
|
class TestComplexConversion(unittest.TestCase):
|
|
"""测试复数类型转换 / Test complex type conversion"""
|
|
|
|
def test_complex64_to_complex128(self):
|
|
"""测试complex64转complex128 / Test complex64 to complex128"""
|
|
z = paddle.to_tensor([1.0 + 2.0j], dtype='complex64')
|
|
z128 = z.cast('complex128')
|
|
self.assertEqual(z128.dtype, paddle.complex128)
|
|
|
|
def test_real_to_complex(self):
|
|
"""测试实数创建复数 / Test creating complex from real"""
|
|
x = paddle.to_tensor([1.0, 2.0, 3.0])
|
|
zeros = paddle.zeros_like(x)
|
|
z = paddle.complex(x, zeros)
|
|
# Imaginary part should be 0
|
|
np.testing.assert_allclose(paddle.imag(z).numpy(), np.zeros(3))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|