Files
2026-07-13 12:40:42 +08:00

1013 lines
36 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Copyright (c) 2021 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.w
import sys
import unittest
import numpy as np
import paddle
sys.path.append("..")
from op_test import OpTest, get_device_place, get_places
from paddle import base
# 2D normal case
class TestSolveOp(OpTest):
def config(self):
self.python_api = paddle.linalg.solve
self.input_x_matrix_shape = [15, 15]
self.input_y_matrix_shape = [15, 10]
self.dtype = "float64"
def setUp(self):
paddle.enable_static()
self.config()
self.op_type = "solve"
np.random.seed(2021)
self.inputs = {
'X': np.random.random(self.input_x_matrix_shape).astype(self.dtype),
'Y': np.random.random(self.input_y_matrix_shape).astype(self.dtype),
}
self.outputs = {
'Out': np.linalg.solve(self.inputs['X'], self.inputs['Y'])
}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(['X', 'Y'], 'Out', check_pir=True)
# x broadcast + 3D batch case
class TestSolveOpBatched_case0(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((11, 11)).astype(self.dtype),
'Y': np.random.random((2, 11, 7)).astype(self.dtype),
}
result = np.linalg.solve(self.inputs['X'], self.inputs['Y'])
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(
['X', 'Y'], 'Out', max_relative_error=1e-1, check_pir=True
)
# 3D batch + y vector case
class TestSolveOpBatched_case1(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((20, 6, 6)).astype(self.dtype),
'Y': np.random.random((20, 6)).astype(self.dtype),
}
result = np.empty_like(self.inputs['Y'])
for i in range(self.inputs['X'].shape[0]):
result[i] = np.linalg.solve(
self.inputs['X'][i], self.inputs['Y'][i]
)
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(
['X', 'Y'], 'Out', max_relative_error=0.04, check_pir=True
)
# 3D batch + y broadcast case
class TestSolveOpBatched_case2(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((2, 10, 10)).astype(self.dtype),
'Y': np.random.random((1, 10, 10)).astype(self.dtype),
}
result = np.linalg.solve(self.inputs['X'], self.inputs['Y'])
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(
['X', 'Y'], 'Out', max_relative_error=0.02, check_pir=True
)
# x broadcast + 3D batch case
class TestSolveOpBatched_case3(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((1, 10, 10)).astype(self.dtype),
'Y': np.random.random((2, 10, 10)).astype(self.dtype),
}
result = np.linalg.solve(self.inputs['X'], self.inputs['Y'])
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(
['X', 'Y'], 'Out', max_relative_error=0.02, check_pir=True
)
# 3D normal batch case
class TestSolveOpBatched_case4(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((3, 6, 6)).astype(self.dtype),
'Y': np.random.random((3, 6, 7)).astype(self.dtype),
}
result = np.linalg.solve(self.inputs['X'], self.inputs['Y'])
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(['X', 'Y'], 'Out', check_pir=True)
# 4D normal batch case
class TestSolveOpBatched_case5(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((2, 2, 6, 6)).astype(self.dtype),
'Y': np.random.random((2, 2, 6, 6)).astype(self.dtype),
}
result = np.linalg.solve(self.inputs['X'], self.inputs['Y'])
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(['X', 'Y'], 'Out', check_pir=True)
# 4D batch + y broadcast case
class TestSolveOpBatched_case6(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((2, 2, 6, 6)).astype(self.dtype),
'Y': np.random.random((1, 2, 6, 9)).astype(self.dtype),
}
result = np.linalg.solve(self.inputs['X'], self.inputs['Y'])
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(['X', 'Y'], 'Out', check_pir=True)
# 5D normal batch case
class TestSolveOpBatched_case7(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((2, 2, 2, 4, 4)).astype(self.dtype),
'Y': np.random.random((2, 2, 2, 4, 4)).astype(self.dtype),
}
result = np.linalg.solve(self.inputs['X'], self.inputs['Y'])
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(
['X', 'Y'], 'Out', max_relative_error=0.04, check_pir=True
)
# 5D batch + y broadcast case
class TestSolveOpBatched_case8(OpTest):
def setUp(self):
self.python_api = paddle.linalg.solve
self.op_type = "solve"
self.dtype = "float64"
np.random.seed(2021)
self.inputs = {
'X': np.random.random((2, 2, 2, 4, 4)).astype(self.dtype),
'Y': np.random.random((1, 2, 2, 4, 7)).astype(self.dtype),
}
result = np.linalg.solve(self.inputs['X'], self.inputs['Y'])
self.outputs = {'Out': result}
def test_check_output(self):
self.check_output(check_pir=True)
def test_check_grad_normal(self):
self.check_grad(
['X', 'Y'], 'Out', max_relative_error=0.04, check_pir=True
)
class TestSolveOpError(unittest.TestCase):
def test_errors(self):
with paddle.static.program_guard(
paddle.static.Program(), paddle.static.Program()
):
# The input type of solve_op must be Variable.
x1 = base.create_lod_tensor(
np.array([[-1]]), [[1]], base.CPUPlace()
)
y1 = base.create_lod_tensor(
np.array([[-1]]), [[1]], base.CPUPlace()
)
self.assertRaises(TypeError, paddle.linalg.solve, x1, y1)
# The data type of input must be float32 or float64.
x2 = paddle.static.data(name="x2", shape=[30, 30], dtype="bool")
y2 = paddle.static.data(name="y2", shape=[30, 10], dtype="bool")
self.assertRaises(TypeError, paddle.linalg.solve, x2, y2)
x3 = paddle.static.data(name="x3", shape=[30, 30], dtype="int32")
y3 = paddle.static.data(name="y3", shape=[30, 10], dtype="int32")
self.assertRaises(TypeError, paddle.linalg.solve, x3, y3)
x4 = paddle.static.data(name="x4", shape=[30, 30], dtype="int64")
y4 = paddle.static.data(name="y4", shape=[30, 10], dtype="int64")
self.assertRaises(TypeError, paddle.linalg.solve, x4, y4)
x5 = paddle.static.data(name="x5", shape=[30, 30], dtype="float16")
y5 = paddle.static.data(name="y5", shape=[30, 10], dtype="float16")
self.assertRaises(TypeError, paddle.linalg.solve, x5, y5)
# The number of dimensions of input'X must be >= 2.
x6 = paddle.static.data(name="x6", shape=[30], dtype="float64")
y6 = paddle.static.data(name="y6", shape=[30], dtype="float64")
self.assertRaises(ValueError, paddle.linalg.solve, x6, y6)
# The inner-most 2 dimensions of input'X should be equal to each other
x7 = paddle.static.data(name="x7", shape=[2, 3, 4], dtype="float64")
y7 = paddle.static.data(name="y7", shape=[2, 4, 3], dtype="float64")
self.assertRaises(ValueError, paddle.linalg.solve, x7, y7)
# The shape of y should not be 1 when left = False. (if y is vector it should be a row vector)
x8 = paddle.static.data(name="x8", shape=[3, 3], dtype="float64")
y8 = paddle.static.data(name="y8", shape=[3], dtype="float64")
self.assertRaises(ValueError, paddle.linalg.solve, x8, y8, False)
# The height of x should equal the width of y when left = False.
x9 = paddle.static.data(name="x9", shape=[2, 5, 5], dtype="float64")
y9 = paddle.static.data(name="y9", shape=[5, 3], dtype="float64")
self.assertRaises(ValueError, paddle.linalg.solve, x9, y9, False)
# 2D + vector case, FP64
class TestSolveOpAPI_1(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float64"
def check_static_result(self, place):
paddle.enable_static()
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=[3, 3], dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=[3], dtype=self.dtype
)
paddle_result = paddle.linalg.solve(paddle_input_x, paddle_input_y)
np_input_x = np.random.random([3, 3]).astype(self.dtype)
np_input_y = np.random.random([3]).astype(self.dtype)
np_result = np.linalg.solve(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=1e-05)
def test_static(self):
for place in self.place:
self.check_static_result(place=place)
def test_dygraph(self):
def run(place):
paddle.disable_static(place)
np.random.seed(2021)
input_x_np = np.random.random([3, 3]).astype(self.dtype)
input_y_np = np.random.random([3]).astype(self.dtype)
tensor_input_x = paddle.to_tensor(input_x_np)
tensor_input_y = paddle.to_tensor(input_y_np)
numpy_output = np.linalg.solve(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(tensor_input_x, tensor_input_y)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=1e-05
)
self.assertEqual(numpy_output.shape, paddle_output.numpy().shape)
paddle.enable_static()
for place in self.place:
run(place)
# 2D normal case, FP64
class TestSolveOpAPI_2(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float64"
def check_static_result(self, place):
paddle.enable_static()
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=[10, 10], dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=[10, 4], dtype=self.dtype
)
paddle_result = paddle.linalg.solve(paddle_input_x, paddle_input_y)
np_input_x = np.random.random([10, 10]).astype(self.dtype)
np_input_y = np.random.random([10, 4]).astype(self.dtype)
np_result = np.linalg.solve(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=1e-05)
def test_static(self):
for place in self.place:
self.check_static_result(place=place)
def test_dygraph(self):
def run(place):
paddle.disable_static(place)
np.random.seed(2021)
input_x_np = np.random.random([10, 10]).astype(self.dtype)
input_y_np = np.random.random([10, 4]).astype(self.dtype)
tensor_input_x = paddle.to_tensor(input_x_np)
tensor_input_y = paddle.to_tensor(input_y_np)
numpy_output = np.linalg.solve(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(tensor_input_x, tensor_input_y)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=1e-05
)
self.assertEqual(numpy_output.shape, paddle_output.numpy().shape)
paddle.enable_static()
for place in self.place:
run(place)
# 2D normal case, FP32
class TestSolveOpAPI_3(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float32"
def check_static_result(self, place):
paddle.enable_static()
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=[10, 10], dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=[10, 4], dtype=self.dtype
)
paddle_result = paddle.linalg.solve(paddle_input_x, paddle_input_y)
np_input_x = np.random.random([10, 10]).astype(self.dtype)
np_input_y = np.random.random([10, 4]).astype(self.dtype)
np_result = np.linalg.solve(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=0.0001)
def test_static(self):
for place in self.place:
self.check_static_result(place=place)
def test_dygraph(self):
def run(place):
paddle.disable_static(place)
np.random.seed(2021)
input_x_np = np.random.random([10, 10]).astype(self.dtype)
input_y_np = np.random.random([10, 4]).astype(self.dtype)
tensor_input_x = paddle.to_tensor(input_x_np)
tensor_input_y = paddle.to_tensor(input_y_np)
numpy_output = np.linalg.solve(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(tensor_input_x, tensor_input_y)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=0.0001
)
self.assertEqual(numpy_output.shape, paddle_output.numpy().shape)
paddle.enable_static()
for place in self.place:
run(place)
# 3D + y broadcast case, FP64
class TestSolveOpAPI_4(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float64"
def check_static_result(self, place):
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=[2, 3, 3], dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=[1, 3, 3], dtype=self.dtype
)
paddle_result = paddle.linalg.solve(paddle_input_x, paddle_input_y)
np_input_x = np.random.random([2, 3, 3]).astype(self.dtype)
np_input_y = np.random.random([1, 3, 3]).astype(self.dtype)
np_result = np.linalg.solve(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=1e-05)
def test_static(self):
for place in self.place:
self.check_static_result(place=place)
def test_dygraph(self):
def run(place):
paddle.disable_static(place)
np.random.seed(2021)
input_x_np = np.random.random([2, 3, 3]).astype(self.dtype)
input_y_np = np.random.random([1, 3, 3]).astype(self.dtype)
tensor_input_x = paddle.to_tensor(input_x_np)
tensor_input_y = paddle.to_tensor(input_y_np)
numpy_output = np.linalg.solve(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(tensor_input_x, tensor_input_y)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=1e-05
)
self.assertEqual(numpy_output.shape, paddle_output.numpy().shape)
paddle.enable_static()
for place in self.place:
run(place)
def np_transpose_last_2dim(x):
x_new_dims = list(range(len(x.shape)))
x_new_dims[-1], x_new_dims[-2] = x_new_dims[-2], x_new_dims[-1]
x = np.transpose(x, x_new_dims)
return x
def np_solve_right(x, y):
x = np_transpose_last_2dim(x)
y = np_transpose_last_2dim(y)
out = np.linalg.solve(x, y)
out = np_transpose_last_2dim(out)
return out
# 2D + vector right case, FP64
class TestSolveOpAPIRight_1(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float64"
def check_static_result(self, place):
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=[3, 3], dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=[1, 3], dtype=self.dtype
)
paddle_result = paddle.linalg.solve(
paddle_input_x, paddle_input_y, left=False
)
np_input_x = np.random.random([3, 3]).astype(self.dtype)
np_input_y = np.random.random([1, 3]).astype(self.dtype)
np_result = np_solve_right(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=1e-05)
def test_static(self):
for place in self.place:
self.check_static_result(place=place)
def test_dygraph(self):
def run(place):
paddle.disable_static(place)
np.random.seed(2021)
input_x_np = np.random.random([3, 3]).astype(self.dtype)
input_y_np = np.random.random([1, 3]).astype(self.dtype)
tensor_input_x = paddle.to_tensor(input_x_np)
tensor_input_y = paddle.to_tensor(input_y_np)
numpy_output = np_solve_right(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(
tensor_input_x, tensor_input_y, left=False
)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=1e-05
)
self.assertEqual(numpy_output.shape, paddle_output.numpy().shape)
paddle.enable_static()
for place in self.place:
run(place)
# 2D normal right case, FP64
class TestSolveOpAPIRight_2(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float64"
def check_static_result(self, place):
paddle.enable_static()
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=[10, 10], dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=[4, 10], dtype=self.dtype
)
paddle_result = paddle.linalg.solve(
paddle_input_x, paddle_input_y, left=False
)
np_input_x = np.random.random([10, 10]).astype(self.dtype)
np_input_y = np.random.random([4, 10]).astype(self.dtype)
np_result = np_solve_right(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=1e-05)
def test_static(self):
for place in self.place:
self.check_static_result(place=place)
def test_dygraph(self):
def run(place):
paddle.disable_static(place)
np.random.seed(2021)
input_x_np = np.random.random([10, 10]).astype(self.dtype)
input_y_np = np.random.random([4, 10]).astype(self.dtype)
tensor_input_x = paddle.to_tensor(input_x_np)
tensor_input_y = paddle.to_tensor(input_y_np)
numpy_output = np_solve_right(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(
tensor_input_x, tensor_input_y, left=False
)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=1e-05
)
self.assertEqual(numpy_output.shape, paddle_output.numpy().shape)
paddle.enable_static()
for place in self.place:
run(place)
# 2D normal right case, FP32
class TestSolveOpAPIRight_3(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float32"
def check_static_result(self, place):
paddle.enable_static()
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=[10, 10], dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=[6, 10], dtype=self.dtype
)
paddle_result = paddle.linalg.solve(
paddle_input_x, paddle_input_y, left=False
)
np_input_x = np.random.random([10, 10]).astype(self.dtype)
np_input_y = np.random.random([6, 10]).astype(self.dtype)
np_result = np_solve_right(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=0.0001)
def test_static(self):
for place in self.place:
self.check_static_result(place=place)
def test_dygraph(self):
def run(place):
paddle.disable_static(place)
np.random.seed(2021)
input_x_np = np.random.random([10, 10]).astype(self.dtype)
input_y_np = np.random.random([6, 10]).astype(self.dtype)
tensor_input_x = paddle.to_tensor(input_x_np)
tensor_input_y = paddle.to_tensor(input_y_np)
numpy_output = np_solve_right(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(
tensor_input_x, tensor_input_y, left=False
)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=0.0001
)
self.assertEqual(numpy_output.shape, paddle_output.numpy().shape)
paddle.enable_static()
for place in self.place:
run(place)
# 3D + y broadcast right case, FP64
class TestSolveOpAPIRight_4(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float64"
def check_static_result(self, place):
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=[2, 3, 3], dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=[1, 3, 3], dtype=self.dtype
)
paddle_result = paddle.linalg.solve(
paddle_input_x, paddle_input_y, left=False
)
np_input_x = np.random.random([2, 3, 3]).astype(self.dtype)
np_input_y = np.random.random([1, 3, 3]).astype(self.dtype)
np_result = np_solve_right(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=1e-05)
def test_static(self):
for place in self.place:
self.check_static_result(place=place)
def test_dygraph(self):
def run(place):
paddle.disable_static(place)
np.random.seed(2021)
input_x_np = np.random.random([2, 3, 3]).astype(self.dtype)
input_y_np = np.random.random([1, 3, 3]).astype(self.dtype)
tensor_input_x = paddle.to_tensor(input_x_np)
tensor_input_y = paddle.to_tensor(input_y_np)
numpy_output = np_solve_right(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(
tensor_input_x, tensor_input_y, left=False
)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=1e-05
)
self.assertEqual(numpy_output.shape, paddle_output.numpy().shape)
paddle.enable_static()
for place in self.place:
run(place)
class TestSolveOpSingularAPI(unittest.TestCase):
# Singular matrix is not invertible
def setUp(self):
self.places = get_places()
self.dtype = "float64"
def check_static_result(self, place):
with base.program_guard(base.Program(), base.Program()):
x = paddle.static.data(name="x", shape=[4, 4], dtype=self.dtype)
y = paddle.static.data(name="y", shape=[4, 4], dtype=self.dtype)
result = paddle.linalg.solve(x, y)
input_x_np = np.ones([4, 4]).astype(self.dtype)
input_y_np = np.ones([4, 4]).astype(self.dtype)
exe = base.Executor(place)
try:
exe.run(
base.default_main_program(),
feed={"x": input_x_np, "y": input_y_np},
fetch_list=[result],
)
except RuntimeError:
print("The mat is singular")
except ValueError:
print("The mat is singular")
def test_static(self):
for place in self.places:
paddle.enable_static()
self.check_static_result(place=place)
def test_dygraph(self):
for place in self.places:
with base.dygraph.guard(place):
input_x_np = np.ones([4, 4]).astype(self.dtype)
input_y_np = np.ones([4, 4]).astype(self.dtype)
input_x = paddle.to_tensor(input_x_np)
input_y = paddle.to_tensor(input_y_np)
try:
paddle.linalg.solve(input_x, input_y)
except RuntimeError:
print("The mat is singular")
except ValueError:
print("The mat is singular")
class TestSolveOpAPIZeroDimCase(unittest.TestCase):
def setUp(self):
np.random.seed(2021)
self.place = get_places()
self.dtype = "float32"
def check_static_result(self, place, x_shape, y_shape, np_y_shape):
paddle.enable_static()
with base.program_guard(base.Program(), base.Program()):
paddle_input_x = paddle.static.data(
name="input_x", shape=x_shape, dtype=self.dtype
)
paddle_input_y = paddle.static.data(
name="input_y", shape=y_shape, dtype=self.dtype
)
paddle_result = paddle.linalg.solve(
paddle_input_x, paddle_input_y, left=False
)
np_input_x = np.random.random(x_shape).astype(self.dtype)
np_input_y = np.random.random(np_y_shape).astype(self.dtype)
np_result = np.linalg.solve(np_input_x, np_input_y)
exe = base.Executor(place)
fetches = exe.run(
base.default_main_program(),
feed={"input_x": np_input_x, "input_y": np_input_y},
fetch_list=[paddle_result],
)
np.testing.assert_allclose(fetches[0], np_result, rtol=0.0001)
def test_static(self):
for place in self.place:
self.check_static_result(
place=place,
x_shape=[10, 0, 0],
y_shape=[10, 0, 0],
np_y_shape=[10, 0, 0],
)
with self.assertRaises(ValueError):
self.check_static_result(
place=place,
x_shape=[10, 0, 0],
y_shape=[10],
np_y_shape=[10],
)
def test_dygraph(self):
def run(place, x_shape, y_shape):
with base.dygraph.guard(place):
input_x_np = np.random.random(x_shape).astype(self.dtype)
input_y_np = np.random.random(y_shape).astype(self.dtype)
tensor_input_x = paddle.to_tensor(
input_x_np, stop_gradient=False
)
tensor_input_y = paddle.to_tensor(
input_y_np, stop_gradient=False
)
numpy_output = np.linalg.solve(input_x_np, input_y_np)
paddle_output = paddle.linalg.solve(
tensor_input_x, tensor_input_y, left=True
)
np.testing.assert_allclose(
numpy_output, paddle_output.numpy(), rtol=0.00011
)
self.assertEqual(
numpy_output.shape, paddle_output.numpy().shape
)
loss = paddle.sum(paddle_output)
loss.backward()
np.testing.assert_allclose(
tensor_input_x.grad.shape, tensor_input_x.shape
)
np.testing.assert_allclose(
tensor_input_y.grad.shape, tensor_input_y.shape
)
for place in self.place:
run(place, x_shape=[1, 10, 10], y_shape=[1, 10, 10])
run(place, x_shape=[0, 10, 10], y_shape=[0, 10, 10])
run(place, x_shape=[0, 10, 10], y_shape=[1, 10, 10])
run(place, x_shape=[10, 0, 0], y_shape=[10, 0, 0])
run(place, x_shape=[10, 1, 1], y_shape=[10, 1, 0])
with self.assertRaises(ValueError):
run(place, x_shape=[10, 0, 0], y_shape=[10])
class TestSolveAPI_Compatibility(unittest.TestCase):
def setUp(self):
np.random.seed(2025)
self.places = ['cpu', get_device_place()]
self.n = 4
self.shape_A = [self.n, self.n]
self.shape_B = [self.n, 1]
self.dtype = "float64"
self.init_data()
def init_data(self):
A = np.random.rand(*self.shape_A).astype(self.dtype)
self.np_A = np.dot(A, A.T) + np.eye(self.n)
self.np_B = np.random.rand(*self.shape_B).astype(self.dtype)
def test_dygraph_Compatibility(self):
paddle.disable_static()
A = paddle.to_tensor(self.np_A)
B = paddle.to_tensor(self.np_B)
paddle_dygraph_out = []
# Position args (args)
out1 = paddle.linalg.solve(A, B)
paddle_dygraph_out.append(out1)
# Key words args (kwargs) for paddle
out2 = paddle.linalg.solve(x=A, y=B)
paddle_dygraph_out.append(out2)
# Key words args for torch compatibility
out3 = paddle.linalg.solve(A=A, B=B)
paddle_dygraph_out.append(out3)
# Key words args for out
out4 = paddle.zeros_like(B)
paddle.linalg.solve(A, B, out=out4)
paddle_dygraph_out.append(out4)
# Numpy reference output
ref_out = np.linalg.solve(self.np_A, self.np_B)
for out in paddle_dygraph_out:
np.testing.assert_allclose(
ref_out, out.numpy(), rtol=1e-05, atol=1e-08
)
paddle.enable_static()
def test_static_Compatibility(self):
paddle.enable_static()
main = paddle.static.Program()
startup = paddle.static.Program()
with paddle.base.program_guard(main, startup):
A = paddle.static.data(
name="A", shape=self.shape_A, dtype=self.dtype
)
B = paddle.static.data(
name="B", shape=self.shape_B, dtype=self.dtype
)
# Position args (args)
out1 = paddle.linalg.solve(A, B)
# Key words args (kwargs) for paddle
out2 = paddle.linalg.solve(x=A, y=B)
# Key words args for torch compatibility
out3 = paddle.linalg.solve(A=A, B=B)
# Numpy reference output
ref_out = np.linalg.solve(self.np_A, self.np_B)
fetch_list = [out1, out2, out3]
for place in self.places:
exe = paddle.base.Executor(place)
fetches = exe.run(
main,
feed={"A": self.np_A, "B": self.np_B},
fetch_list=fetch_list,
)
for out in fetches:
np.testing.assert_allclose(
out, ref_out, rtol=1e-05, atol=1e-08
)
if __name__ == "__main__":
unittest.main()