867 lines
23 KiB
Python
867 lines
23 KiB
Python
# 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
|
|
|
|
sys.path.append("..")
|
|
from op_test import OpTest, get_places
|
|
|
|
import paddle
|
|
from paddle import base
|
|
from paddle.base import Program, program_guard
|
|
|
|
paddle.enable_static()
|
|
|
|
|
|
# 2D + 2D , test 'upper'
|
|
class TestTriangularSolveOp(OpTest):
|
|
"""
|
|
case 1
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [12, 12]
|
|
self.y_shape = [12, 10]
|
|
self.upper = True
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
self.output = np.linalg.solve(
|
|
np.triu(self.inputs['X']), self.inputs['Y']
|
|
)
|
|
|
|
def setUp(self):
|
|
self.op_type = "triangular_solve"
|
|
self.python_api = paddle.tensor.linalg.triangular_solve
|
|
self.config()
|
|
|
|
if self.dtype is np.complex64 or self.dtype is np.complex128:
|
|
self.inputs = {
|
|
'X': (
|
|
np.random.random(self.x_shape)
|
|
+ 1j * np.random.random(self.x_shape)
|
|
).astype(self.dtype),
|
|
'Y': (
|
|
np.random.random(self.y_shape)
|
|
+ 1j * np.random.random(self.y_shape)
|
|
).astype(self.dtype),
|
|
}
|
|
else:
|
|
self.inputs = {
|
|
'X': np.random.random(self.x_shape).astype(self.dtype),
|
|
'Y': np.random.random(self.y_shape).astype(self.dtype),
|
|
}
|
|
|
|
self.attrs = {
|
|
'upper': self.upper,
|
|
'transpose': self.transpose,
|
|
'unitriangular': self.unitriangular,
|
|
}
|
|
self.set_output()
|
|
self.outputs = {'Out': self.output}
|
|
|
|
def test_check_output(self):
|
|
self.check_output(check_cinn=True, check_pir=True)
|
|
|
|
def test_check_grad_normal(self):
|
|
self.check_grad(['X', 'Y'], 'Out', check_cinn=True, check_pir=True)
|
|
|
|
|
|
# 2D(broadcast) + 3D, test 'transpose'
|
|
class TestTriangularSolveOp2(TestTriangularSolveOp):
|
|
"""
|
|
case 2
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [10, 10]
|
|
self.y_shape = [3, 10, 8]
|
|
self.upper = False
|
|
self.transpose = True
|
|
self.unitriangular = False
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X']).transpose(1, 0)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
|
|
# 3D(broadcast) + 3D
|
|
class TestTriangularSolveOp3(TestTriangularSolveOp):
|
|
"""
|
|
case 3
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [1, 10, 10]
|
|
self.y_shape = [6, 10, 12]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
|
|
# 3D + 3D(broadcast), test 'transpose'
|
|
class TestTriangularSolveOp4(TestTriangularSolveOp):
|
|
"""
|
|
case 4
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [3, 10, 10]
|
|
self.y_shape = [1, 10, 12]
|
|
self.upper = True
|
|
self.transpose = True
|
|
self.unitriangular = False
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
x = np.triu(self.inputs['X']).transpose(0, 2, 1)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
|
|
# 2D + 2D , test 'unitriangular' specially
|
|
class TestTriangularSolveOp5(TestTriangularSolveOp):
|
|
"""
|
|
case 5
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [10, 10]
|
|
self.y_shape = [10, 10]
|
|
self.upper = True
|
|
self.transpose = False
|
|
self.unitriangular = True
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
x = np.triu(self.inputs['X'])
|
|
np.fill_diagonal(x, 1.0)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
def test_check_grad_normal(self):
|
|
x = np.triu(self.inputs['X'])
|
|
np.fill_diagonal(x, 1.0)
|
|
grad_out = np.ones([10, 10]).astype('float64')
|
|
grad_y = np.linalg.solve(x.transpose(1, 0), grad_out)
|
|
|
|
grad_x = -np.matmul(grad_y, self.output.transpose(1, 0))
|
|
grad_x = np.triu(grad_x)
|
|
np.fill_diagonal(grad_x, 0.0)
|
|
|
|
self.check_grad(
|
|
['X', 'Y'],
|
|
'Out',
|
|
user_defined_grads=[grad_x, grad_y],
|
|
user_defined_grad_outputs=[grad_out],
|
|
)
|
|
|
|
|
|
# 4D(broadcast) + 4D(broadcast)
|
|
class TestTriangularSolveOp6(TestTriangularSolveOp):
|
|
"""
|
|
case 6
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [1, 3, 10, 10]
|
|
self.y_shape = [2, 1, 10, 5]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
|
|
# 3D(broadcast) + 4D(broadcast), test 'upper'
|
|
class TestTriangularSolveOp7(TestTriangularSolveOp):
|
|
"""
|
|
case 7
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [2, 10, 10]
|
|
self.y_shape = [5, 1, 10, 2]
|
|
self.upper = True
|
|
self.transpose = True
|
|
self.unitriangular = False
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
x = np.triu(self.inputs['X']).transpose(0, 2, 1)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
|
|
# 3D(broadcast) + 5D
|
|
class TestTriangularSolveOp8(TestTriangularSolveOp):
|
|
"""
|
|
case 8
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [12, 3, 3]
|
|
self.y_shape = [2, 3, 12, 3, 2]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
|
|
# 5D + 4D(broadcast)
|
|
class TestTriangularSolveOp9(TestTriangularSolveOp):
|
|
"""
|
|
case 9
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [2, 4, 2, 3, 3]
|
|
self.y_shape = [4, 1, 3, 10]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = "float64"
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.matmul(np.linalg.inv(x), y)
|
|
|
|
|
|
# 3D(broadcast) + 3D complex64
|
|
class TestTriangularSolveOpCp643b3(TestTriangularSolveOp):
|
|
"""
|
|
case 10
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [1, 10, 10]
|
|
self.y_shape = [6, 10, 12]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex64
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 2D + 2D upper complex64
|
|
class TestTriangularSolveOpCp6422Up(TestTriangularSolveOp):
|
|
"""
|
|
case 11
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [12, 12]
|
|
self.y_shape = [12, 10]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex64
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
max_relative_error=0.02,
|
|
)
|
|
|
|
|
|
# 2D(broadcast) + 3D, test 'transpose' complex64
|
|
class TestTriangularSolveOpCp6423T(TestTriangularSolveOp):
|
|
"""
|
|
case 12
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [10, 10]
|
|
self.y_shape = [3, 10, 8]
|
|
self.upper = False
|
|
self.transpose = True
|
|
self.unitriangular = False
|
|
self.dtype = np.complex64
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X']).transpose(1, 0)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 2D + 2D , test 'unitriangular' complex64
|
|
class TestTriangularSolveOpCp6422Un(TestTriangularSolveOp):
|
|
"""
|
|
case 13
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [10, 10]
|
|
self.y_shape = [10, 10]
|
|
self.upper = True
|
|
self.transpose = False
|
|
self.unitriangular = True
|
|
self.dtype = np.complex64
|
|
|
|
def set_output(self):
|
|
x = np.triu(self.inputs['X'])
|
|
np.fill_diagonal(x, 1.0 + 0j)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
def test_check_output(self):
|
|
self.check_output(check_pir=True)
|
|
|
|
def test_check_grad_normal(self):
|
|
self.check_grad(['X', 'Y'], 'Out')
|
|
|
|
|
|
# 4D(broadcast) + 4D(broadcast) complex64
|
|
class TestTriangularSolveOpCp644b4b(TestTriangularSolveOp):
|
|
"""
|
|
case 14
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [1, 3, 10, 10]
|
|
self.y_shape = [2, 3, 10, 5]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex64
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
max_relative_error=0.009,
|
|
)
|
|
|
|
|
|
# 3D(broadcast) + 4D(broadcast), test 'upper' complex64
|
|
class TestTriangularSolveOpCp643b4bUp(TestTriangularSolveOp):
|
|
"""
|
|
case 15
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [2, 10, 10]
|
|
self.y_shape = [5, 1, 10, 2]
|
|
self.upper = True
|
|
self.transpose = True
|
|
self.unitriangular = False
|
|
self.dtype = np.complex64
|
|
|
|
def set_output(self):
|
|
x = np.triu(self.inputs['X']).transpose(0, 2, 1)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 3D(broadcast) + 5D complex64
|
|
class TestTriangularSolveOpCp643b5(TestTriangularSolveOp):
|
|
"""
|
|
case 16
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [12, 3, 3]
|
|
self.y_shape = [2, 3, 12, 3, 2]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex64
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 5D + 4D(broadcast) complex64
|
|
class TestTriangularSolveOpCp6454b(TestTriangularSolveOp):
|
|
"""
|
|
case 17
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [2, 4, 2, 3, 3]
|
|
self.y_shape = [4, 1, 3, 10]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex64
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.matmul(np.linalg.inv(x), 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,
|
|
)
|
|
|
|
|
|
# 3D(broadcast) + 3D complex128
|
|
class TestTriangularSolveOpCp1283b3(TestTriangularSolveOp):
|
|
"""
|
|
case 18
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [1, 10, 10]
|
|
self.y_shape = [6, 10, 12]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex128
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 2D + 2D upper complex128
|
|
class TestTriangularSolveOpCp12822Up(TestTriangularSolveOp):
|
|
"""
|
|
case 19
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [12, 12]
|
|
self.y_shape = [12, 10]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex128
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 2D(broadcast) + 3D, test 'transpose' complex128
|
|
class TestTriangularSolveOpCp12823T(TestTriangularSolveOp):
|
|
"""
|
|
case 20
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [10, 10]
|
|
self.y_shape = [3, 10, 8]
|
|
self.upper = False
|
|
self.transpose = True
|
|
self.unitriangular = False
|
|
self.dtype = np.complex128
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X']).transpose(1, 0)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 2D + 2D , test 'unitriangular' complex128
|
|
class TestTriangularSolveOpCp12822Un(TestTriangularSolveOp):
|
|
"""
|
|
case 21
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [10, 10]
|
|
self.y_shape = [10, 10]
|
|
self.upper = True
|
|
self.transpose = False
|
|
self.unitriangular = True
|
|
self.dtype = np.complex128
|
|
|
|
def set_output(self):
|
|
x = np.triu(self.inputs['X'])
|
|
np.fill_diagonal(x, 1.0 + 0j)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, y)
|
|
|
|
def test_check_output(self):
|
|
self.check_output(check_pir=True)
|
|
|
|
def test_check_grad_normal(self):
|
|
self.check_grad(
|
|
['X', 'Y'],
|
|
'Out',
|
|
)
|
|
|
|
|
|
# 4D(broadcast) + 4D(broadcast) complex128
|
|
class TestTriangularSolveOpCp1284b4b(TestTriangularSolveOp):
|
|
"""
|
|
case 22
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [1, 3, 10, 10]
|
|
self.y_shape = [2, 3, 10, 5]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex128
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 3D(broadcast) + 4D(broadcast), test 'upper' complex128
|
|
class TestTriangularSolveOpCp1283b4bUp(TestTriangularSolveOp):
|
|
"""
|
|
case 23
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [2, 10, 10]
|
|
self.y_shape = [5, 1, 10, 2]
|
|
self.upper = True
|
|
self.transpose = True
|
|
self.unitriangular = False
|
|
self.dtype = np.complex128
|
|
|
|
def set_output(self):
|
|
x = np.triu(self.inputs['X']).transpose(0, 2, 1)
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 3D(broadcast) + 5D complex128
|
|
class TestTriangularSolveOpCp1283b5(TestTriangularSolveOp):
|
|
"""
|
|
case 24
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [12, 3, 3]
|
|
self.y_shape = [2, 3, 12, 3, 2]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex128
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.linalg.solve(x, 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,
|
|
)
|
|
|
|
|
|
# 5D + 4D(broadcast) complex128
|
|
class TestTriangularSolveOpCp12854b(TestTriangularSolveOp):
|
|
"""
|
|
case 25
|
|
"""
|
|
|
|
def config(self):
|
|
self.x_shape = [2, 4, 2, 3, 3]
|
|
self.y_shape = [4, 1, 3, 10]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = np.complex128
|
|
|
|
def set_output(self):
|
|
x = np.tril(self.inputs['X'])
|
|
y = self.inputs['Y']
|
|
self.output = np.matmul(np.linalg.inv(x), 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,
|
|
)
|
|
|
|
|
|
class TestTriangularSolveAPI(unittest.TestCase):
|
|
def setUp(self):
|
|
np.random.seed(2021)
|
|
self.place = get_places()
|
|
self.dtype = "float64"
|
|
|
|
def check_static_result(self, place):
|
|
with paddle.static.program_guard(
|
|
paddle.static.Program(), paddle.static.Program()
|
|
):
|
|
x = paddle.static.data(name="x", shape=[3, 3], dtype=self.dtype)
|
|
y = paddle.static.data(name="y", shape=[3, 2], dtype=self.dtype)
|
|
z = paddle.linalg.triangular_solve(x, y)
|
|
|
|
x_np = np.random.random([3, 3]).astype(self.dtype)
|
|
y_np = np.random.random([3, 2]).astype(self.dtype)
|
|
z_np = np.linalg.solve(np.triu(x_np), y_np)
|
|
|
|
exe = base.Executor(place)
|
|
fetches = exe.run(
|
|
paddle.static.default_main_program(),
|
|
feed={"x": x_np, "y": y_np},
|
|
fetch_list=[z],
|
|
)
|
|
np.testing.assert_allclose(fetches[0], z_np, 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)
|
|
x_np = np.random.random([3, 3]).astype(self.dtype)
|
|
y_np = np.random.random([3, 2]).astype(self.dtype)
|
|
z_np = np.linalg.solve(np.tril(x_np), y_np)
|
|
|
|
x = paddle.to_tensor(x_np)
|
|
y = paddle.to_tensor(y_np)
|
|
z = paddle.linalg.triangular_solve(x, y, upper=False)
|
|
|
|
np.testing.assert_allclose(z_np, z.numpy(), rtol=1e-05)
|
|
self.assertEqual(z_np.shape, z.numpy().shape)
|
|
paddle.enable_static()
|
|
|
|
for place in self.place:
|
|
run(place)
|
|
|
|
|
|
class TestTriangularSolveOpError(unittest.TestCase):
|
|
def test_errors1(self):
|
|
with program_guard(Program(), 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.triangular_solve, x1, y1)
|
|
|
|
def test_errors2(self):
|
|
with paddle.static.program_guard(
|
|
paddle.static.Program(), paddle.static.Program()
|
|
):
|
|
# 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.triangular_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.triangular_solve, x3, y3)
|
|
|
|
x4 = paddle.static.data(name="x4", shape=[30, 30], dtype="float16")
|
|
y4 = paddle.static.data(name="y4", shape=[30, 10], dtype="float16")
|
|
self.assertRaises(TypeError, paddle.linalg.triangular_solve, x4, y4)
|
|
|
|
# The number of dimensions of input'X must be >= 2.
|
|
x5 = paddle.static.data(name="x5", shape=[30], dtype="float64")
|
|
y5 = paddle.static.data(name="y5", shape=[30, 30], dtype="float64")
|
|
self.assertRaises(
|
|
ValueError, paddle.linalg.triangular_solve, x5, y5
|
|
)
|
|
|
|
# The number of dimensions of input'Y must be >= 2.
|
|
x6 = paddle.static.data(name="x6", shape=[30, 30], dtype="float64")
|
|
y6 = paddle.static.data(name="y6", shape=[30], dtype="float64")
|
|
self.assertRaises(
|
|
ValueError, paddle.linalg.triangular_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.triangular_solve, x7, y7
|
|
)
|
|
|
|
|
|
class TestTriangularSolveOp_ZeroSize(TestTriangularSolveOp):
|
|
def config(self):
|
|
self.__class__.exist_fp64_check_grad = True
|
|
self.x_shape = [0, 2, 2]
|
|
self.y_shape = [0, 2, 1]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = "float32"
|
|
|
|
|
|
class TestTriangularSolveOp_ZeroSize2(TestTriangularSolveOp_ZeroSize):
|
|
def config(self):
|
|
self.__class__.exist_fp64_check_grad = True
|
|
self.x_shape = [3, 3]
|
|
self.y_shape = [3, 0]
|
|
self.upper = False
|
|
self.transpose = False
|
|
self.unitriangular = False
|
|
self.dtype = "float32"
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|