未验证 提交 49265879 编写于 作者: C chentianyu03 提交者: GitHub

remove complex module direction (#29419) (#29460)

上级 08ee7485
# Copyright (c) 2020 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.
from . import tensor
from .tensor_op_patch import monkey_patch_math_complex
from .tensor import *
__all__ = tensor.__all__ + []
monkey_patch_math_complex()
# Copyright (c) 2020 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.
from ...fluid import framework
def is_complex(x):
"""
Return true if the input(x) is a ComplexVariable.
"""
return isinstance(x, framework.ComplexVariable)
def is_real(x):
"""
Return true if the input(x) is a real number Variable.
"""
return isinstance(x, framework.Variable)
def complex_variable_exists(inputs, layer_name):
for inp in inputs:
if is_complex(inp):
return
err_msg = "At least one inputs of layer complex." if len(inputs) > 1 \
else "The input of layer complex."
raise ValueError(err_msg + layer_name +
"() must be ComplexVariable, please "
"use the layer for real numher instead.")
# Copyright (c) 2020 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.
from . import linalg
from . import math
from . import manipulation
from .linalg import *
from .math import *
from .manipulation import *
__all__ = math.__all__
__all__ += linalg.__all__
__all__ += manipulation.__all__
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
#
# 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.
from ..helper import is_complex, is_real, complex_variable_exists
from ....fluid.framework import ComplexVariable
from ....fluid import layers
__all__ = ['matmul', ]
def matmul(x, y, transpose_x=False, transpose_y=False, alpha=1.0, name=None):
"""
Applies matrix multiplication to two complex number tensors. See the
detailed description in :ref:`api_fluid_layers_matmul`.
Args:
x (ComplexVariable|Variable): The first input, can be a ComplexVariable
with data type complex64 or complex128, or a Variable with data type
float32 or float64.
y (ComplexVariable|Variable): The second input, can be a ComplexVariable
with data type complex64 or complex128, or a Variable with data type
float32 or float64.
transpose_x (bool): Whether to transpose :math:`x` before multiplication.
transpose_y (bool): Whether to transpose :math:`y` before multiplication.
alpha (float): The scale of output. Default 1.0.
name(str|None): A name for this layer(optional). If set None, the layer
will be named automatically.
Returns:
ComplexVariable: The product result, with the same data type as inputs.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.fluid.dygraph as dg
with dg.guard():
x = np.array([[1.0 + 1j, 2.0 + 1j], [3.0+1j, 4.0+1j]])
y = np.array([1.0 + 1j, 1.0 + 1j])
x_var = dg.to_variable(x)
y_var = dg.to_variable(y)
result = paddle.complex.matmul(x_var, y_var)
print(result.numpy())
# [1.+5.j 5.+9.j]
"""
# x = a + bi, y = c + di
# P1 = ac; P2 = (a + b)(c + d); P3 = bd; then mm(x, y) = (P1-P3) + (P2-P1-P3)j
complex_variable_exists([x, y], "matmul")
a, b = (x.real, x.imag) if is_complex(x) else (x, None)
c, d = (y.real, y.imag) if is_complex(y) else (y, None)
P1 = layers.matmul(a, c, transpose_x, transpose_y, alpha, name)
if is_real(b) and is_real(d):
P2 = layers.matmul(a + b, c + d, transpose_x, transpose_y, alpha, name)
P3 = layers.matmul(b, d, transpose_x, transpose_y, alpha, name)
real = P1 - P3
imag = P2 - P1 - P3
elif is_real(b):
real = P1
imag = layers.matmul(b, c, transpose_x, transpose_y, alpha, name)
else:
real = P1
imag = layers.matmul(a, d, transpose_x, transpose_y, alpha, name)
return ComplexVariable(real, imag)
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
#
# 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.
from paddle.common_ops_import import *
from ..helper import is_complex, is_real, complex_variable_exists
from ....fluid.framework import ComplexVariable
from ....fluid import layers
__all__ = [
'reshape',
'transpose',
]
def reshape(x, shape, inplace=False, name=None):
"""
To change the shape of ``x`` without changing its data.
There are some tricks when specifying the target shape.
1. -1 means the value of this dimension is inferred from the total element
number of x and remaining dimensions. Thus one and only one dimension can
be set -1.
2. 0 means the actual dimension value is going to be copied from the
corresponding dimension of x. The index of 0s in shape can not exceed
the dimension of x.
Here are some examples to explain it.
1. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape
is [6, 8], the reshape operator will transform x into a 2-D tensor with
shape [6, 8] and leaving x's data unchanged.
2. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape
specified is [2, 3, -1, 2], the reshape operator will transform x into a
4-D tensor with shape [2, 3, 4, 2] and leaving x's data unchanged. In this
case, one dimension of the target shape is set to -1, the value of this
dimension is inferred from the total element number of x and remaining
dimensions.
3. Given a 3-D tensor x with a shape [2, 4, 6], and the target shape
is [-1, 0, 3, 2], the reshape operator will transform x into a 4-D tensor
with shape [2, 4, 3, 2] and leaving x's data unchanged. In this case,
besides -1, 0 means the actual dimension value is going to be copied from
the corresponding dimension of x.
Args:
x(ComplexVariable): the input. A ``Tensor`` or ``LoDTensor`` , data
type: ``complex64`` or ``complex128``.
shape(list|tuple|Variable): target shape. At most one dimension of
the target shape can be -1. If ``shape`` is a list or tuple, the
elements of it should be integers or Tensors with shape [1] and
data type ``int32``. If ``shape`` is an Variable, it should be
an 1-D Tensor of data type ``int32``.
inplace(bool, optional): If ``inplace`` is True, the output of
``reshape`` is the same ComplexVariable as the input. Otherwise,
the input and output of ``reshape`` are different
ComplexVariables. Defaults to False. Note that if ``x``is more
than one OPs' input, ``inplace`` must be False.
name(str, optional): The default value is None. Normally there is no
need for user to set this property. For more information, please
refer to :ref:`api_guide_Name` .
Returns:
ComplexVariable: A ``Tensor`` or ``LoDTensor``. The data type is same as ``x``. It is a new ComplexVariable if ``inplace`` is ``False``, otherwise it is ``x``.
Raises:
ValueError: If more than one elements of ``shape`` is -1.
ValueError: If the element of ``shape`` is 0, the corresponding dimension should be less than or equal to the dimension of ``x``.
ValueError: If the elements in ``shape`` is negative except -1.
Examples:
.. code-block:: python
import paddle.fluid as fluid
import paddle.complex as cpx
import paddle.fluid.dygraph as dg
import numpy as np
x_np = np.random.randn(2, 3, 4) + 1j * np.random.randn(2, 3, 4)
place = fluid.CPUPlace()
with dg.guard(place):
x_var = dg.to_variable(x_np)
y_var = cpx.reshape(x_var, (2, -1))
y_np = y_var.numpy()
print(y_np.shape)
# (2, 12)
"""
complex_variable_exists([x], "reshape")
if inplace:
x.real = fluid.layers.reshape(x.real, shape, inplace=inplace, name=name)
x.imag = fluid.layers.reshape(x.imag, shape, inplace=inplace, name=name)
return x
out_real = fluid.layers.reshape(x.real, shape, inplace=inplace, name=name)
out_imag = fluid.layers.reshape(x.imag, shape, inplace=inplace, name=name)
return ComplexVariable(out_real, out_imag)
def transpose(x, perm, name=None):
"""
Permute the data dimensions for complex number :attr:`input` according to `perm`.
See :ref:`api_fluid_layers_transpose` for the real number API.
Args:
x (ComplexVariable): The input n-D ComplexVariable with data type
complex64 or complex128.
perm (list): Permute the input according to the value of perm.
name (str): The name of this layer. It is optional.
Returns:
ComplexVariable: A transposed n-D ComplexVariable, with the same data type as :attr:`input`.
Examples:
.. code-block:: python
import paddle
x = paddle.to_tensor([[1.0 + 1.0j, 2.0 + 1.0j], [3.0+1.0j, 4.0+1.0j], [5.0+1.0j, 6.0+1.0j]])
x_transposed = paddle.complex.transpose(x, [1, 0])
print(x_transposed.numpy())
#[[1.+1.j 3.+1.j 5.+1.j]
# [2.+1.j 4.+1.j 6.+1.j]]
"""
complex_variable_exists([x], "transpose")
real = layers.transpose(x.real, perm, name)
imag = layers.transpose(x.imag, perm, name)
return ComplexVariable(real, imag)
# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve.
#
# 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.
from paddle.common_ops_import import *
from ..helper import is_complex, is_real, complex_variable_exists
from ....fluid.framework import ComplexVariable
from ....fluid import layers
from ....tensor import math
__all__ = [
'elementwise_add',
'elementwise_sub',
'elementwise_mul',
'elementwise_div',
'kron',
'trace',
'sum',
]
def elementwise_add(x, y, axis=-1, name=None):
"""
The element-wise addition layer for complex number inputs. At least one of
inputs :attr:`x` and :attr:`y` must be a ComplexVariable. See the detailed
description for the function and other arguments
in :ref:`api_fluid_layers_elementwise_add` .
Args:
x (Variable|ComplexVariable): The first input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
y (Variable|ComplexVariable): The second input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
name(str, optional): The default value is None. Normally there is no
need for user to set this property. For more information, please
refer to :ref:`api_guide_Name`.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.fluid.dygraph as dg
a = np.array([[1.0+1.0j, 2.0+1.0j], [3.0+1.0j, 4.0+1.0j]])
b = np.array([[5.0+2.0j, 6.0+2.0j], [7.0+2.0j, 8.0+2.0j]])
with dg.guard():
x = dg.to_variable(a)
y = dg.to_variable(b)
out = paddle.complex.elementwise_add(x, y)
print(out.numpy())
# [[ 6.+3.j 8.+3.j]
# [10.+3.j 12.+3.j]]
"""
complex_variable_exists([x, y], "elementwise_add")
(x_real, x_imag) = (x.real, x.imag) if is_complex(x) else (x, None)
(y_real, y_imag) = (y.real, y.imag) if is_complex(y) else (y, None)
real = layers.elementwise_add(x_real, y_real, axis=axis, name=name)
if is_real(x_imag) and is_real(y_imag):
imag = layers.elementwise_add(x_imag, y_imag, axis=axis, name=name)
elif is_real(x_imag):
imag = layers.assign(x_imag)
else:
imag = layers.elementwise_add(
layers.zeros_like(x_real), y_imag, axis=axis, name=name)
return ComplexVariable(real, imag)
def elementwise_sub(x, y, axis=-1, name=None):
"""
The element-wise subtraction layer for complex number inputs. At least one of
inputs :attr:`x` and :attr:`y` must be a ComplexVariable. See the detailed
description for the function and other arguments
in :ref:`api_fluid_layers_elementwise_sub` .
Args:
x (Variable|ComplexVariable): The first input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
y (Variable|ComplexVariable): The second input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
name(str, optional): The default value is None. Normally there is no
need for user to set this property. For more information, please
refer to :ref:`api_guide_Name`.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.fluid.dygraph as dg
a = np.array([[1.0+1.0j, 2.0+1.0j], [3.0+1.0j, 4.0+1.0j]])
b = np.array([[5.0+2.0j, 6.0+2.0j], [7.0+2.0j, 8.0+2.0j]])
with dg.guard():
x = dg.to_variable(a)
y = dg.to_variable(b)
out = paddle.complex.elementwise_sub(x, y)
print(out.numpy())
# [[-4.-1.j -4.-1.j]
# [-4.-1.j -4.-1.j]]
"""
complex_variable_exists([x, y], "elementwise_sub")
(x_real, x_imag) = (x.real, x.imag) if is_complex(x) else (x, None)
(y_real, y_imag) = (y.real, y.imag) if is_complex(y) else (y, None)
real = layers.elementwise_sub(x_real, y_real, axis=axis, name=name)
if is_real(x_imag) and is_real(y_imag):
imag = layers.elementwise_sub(x_imag, y_imag, axis=axis, name=name)
elif is_real(x_imag):
imag = layers.assign(x_imag)
else:
imag = layers.elementwise_sub(
layers.zeros_like(x_real), y_imag, axis=axis, name=name)
return ComplexVariable(real, imag)
def elementwise_mul(x, y, axis=-1, name=None):
"""
The element-wise multiplication layer for complex number inputs. At least
one of inputs :attr:`x` and :attr:`y` must be a ComplexVariable. See the
detailed description for the function and other arguments
in :ref:`api_fluid_layers_elementwise_mul` .
Args:
x (Variable|ComplexVariable): The first input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
y (Variable|ComplexVariable): The second input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
name(str, optional): The default value is None. Normally there is no
need for user to set this property. For more information, please
refer to :ref:`api_guide_Name`.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.fluid.dygraph as dg
a = np.array([[1.0+1.0j, 2.0+1.0j], [3.0+1.0j, 4.0+1.0j]])
b = np.array([[5.0+2.0j, 6.0+2.0j], [7.0+2.0j, 8.0+2.0j]])
with dg.guard():
x = dg.to_variable(a)
y = dg.to_variable(b)
out = paddle.complex.elementwise_mul(x, y)
print(out.numpy())
# [[ 3. +7.j 10.+10.j]
# [19.+13.j 30.+16.j]]
"""
complex_variable_exists([x, y], "elementwise_mul")
# (a + bi)(c + di) = (ac - bd) + (bc + ad)i
(a, b) = (x.real, x.imag) if is_complex(x) else (x, None)
(c, d) = (y.real, y.imag) if is_complex(y) else (y, None)
ac = layers.elementwise_mul(a, c, axis=axis, name=name)
bd = layers.elementwise_mul(
b, d, axis=axis, name=name) if is_real(b) and is_real(d) else None
bc = layers.elementwise_mul(
b, c, axis=axis, name=name) if is_real(b) else None
ad = layers.elementwise_mul(
a, d, axis=axis, name=name) if is_real(d) else None
real = ac - bd if is_real(bd) else ac
imag = bc + ad if is_real(bc) and is_real(ad) else bc if is_real(bc) else ad
return ComplexVariable(real, imag)
def elementwise_div(x, y, axis=-1, name=None):
"""
The element-wise division layer for complex number inputs. At least one of
inputs :attr:`x` and :attr:`y` must be a ComplexVariable. See the detailed
description for the function and other arguments
in :ref:`api_fluid_layers_elementwise_div` .
Args:
x (Variable|ComplexVariable): The first input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
y (Variable|ComplexVariable): The second input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
name(str, optional): The default value is None. Normally there is no
need for user to set this property. For more information, please
refer to :ref:`api_guide_Name`.
Examples:
.. code-block:: python
import numpy as np
import paddle
import paddle.fluid.dygraph as dg
a = np.array([[1.0+1.0j, 2.0+1.0j], [3.0+1.0j, 4.0+1.0j]])
b = np.array([[5.0+2.0j, 6.0+2.0j], [7.0+2.0j, 8.0+2.0j]])
with dg.guard():
x = dg.to_variable(a)
y = dg.to_variable(b)
out = paddle.complex.elementwise_div(x, y)
print(out.numpy())
# [[0.24137931+0.10344828j 0.35 +0.05j ]
# [0.43396226+0.01886792j 0.5 +0.j ]]
"""
complex_variable_exists([x, y], "elementwise_div")
# (a + bi)/(c + di) = (a + bi)(c - di)/(c^2 + d^2)
(c, d) = (y.real, y.imag) if is_complex(y) else (y, None)
y_conj = ComplexVariable(c, -d) if is_real(d) else c
e = 1 / (layers.pow(c, 2.0) + layers.pow(d, 2.0)
) if is_real(d) else 1 / layers.pow(c, 2.0)
return elementwise_mul(
elementwise_mul(
x, y_conj, axis=axis, name=name),
e,
axis=axis,
name=name)
def trace(x, offset=0, axis1=0, axis2=1, name=None):
"""
The layer to compute the trace for a complex number tensor. x :attr:`x` must be a ComplexVariable.
See the detailed description for the function and other arguments
in :ref:`api_tensor_math_trace` .
Args:
x(ComplexVariable): The input ComplexVariable x. Must be at least 2-dimensional.
The supported data types include complex64 and complex128.
offset(int, optional): Which diagonals in input tensor x will be taken. Default: 0 (main diagonals).
axis1(int, optional): The first axis with respect to take diagonal. Default: 0.
axis2(int, optional): The second axis with respect to take diagonal. Default: 1.
name (str, optional): Normally there is no need for user to set this property. For more information, please refer to :ref:`api_guide_Name`. Default: None.
Returns:
ComplexVariable: The trace result of input tensor x, it's data type is the same as input data type.
Examples:
.. code-block:: python
import paddle
import numpy as np
case1 = np.random.randn(3, 10, 10).astype('float64') + 1j * np.random.randn(3, 10, 10).astype('float64')
paddle.disable_static()
case1 = paddle.to_tensor(case1)
data1 = paddle.complex.trace(case1, offset=1, axis1=1, axis2=2) # data1.shape = [3]
"""
complex_variable_exists([x], "trace")
real = math.trace(x.real, offset, axis1, axis2, name)
imag = math.trace(x.imag, offset, axis1, axis2, name)
return ComplexVariable(real, imag)
def sum(input, dim=None, keep_dim=False, name=None):
"""
The layer to compute the sum for a complex number tensor elements over the given dimension. input :attr:`input` must be a ComplexVariable.
See the detailed description for the function and other arguments
in :ref:`api_tensor_math_sum` .
Args:
input(ComplexVariable): The input ComplexVariable with any number of dimensions.
The supported data types include complex64 and complex128.
dim (list|int, optional): The dimensions along which the sum is performed. If
:attr:`None`, sum all elements of :attr:`input` and return a
Tensor variable with a single element, otherwise must be in the
range :math:`[-rank(input), rank(input))`. If :math:`dim[i] < 0`,
the dimension to reduce is :math:`rank + dim[i]`.
keep_dim (bool, optional): Whether to reserve the reduced dimension in the
output Tensor. The result tensor will have one fewer dimension
than the :attr:`input` unless :attr:`keep_dim` is true, default
value is False.
name(str, optional): The default value is None. Normally there is no need for
user to set this property. For more information, please refer to :ref:`api_guide_Name`
Returns:
ComplexVariable: Results of summation operation on the specified dim of input tensor,
it's data type is the same as input.
Raises:
ValueError: the :attr:`dtype` must be float64 or int64.
Examples:
.. code-block:: python
import paddle.complex as cpx
import paddle.fluid.dygraph as dg
import numpy as np
with dg.guard():
# x is a Tensor variable with following elements:
# [[0.2, 0.3, 0.5, 0.9],
# [0.1, 0.2, 0.6, 0.7]]
# Each example is followed by the corresponding output tensor.
x = np.array([[0.2, 0.3, 0.5, 0.9],[0.1, 0.2, 0.6, 0.7]]) + 1j * np.array([[0.3, 0.4, 0.5, 0.2],[0.3, 0.6, 0.8, 0.3]])
x = dg.to_variable(x)
out1 = cpx.sum(x) # [3.5+3.4j]
out2 = cpx.sum(x, dim=0) # [0.3+0.6j, 0.5+1.j, 1.1+1.3j, 1.6+0.5j]
out3 = cpx.sum(x, dim=-1) # [1.9+1.4j, 1.6+2.j]
out4 = cpx.sum(x, dim=1, keep_dim=True) # [[1.9+1.4j], [1.6+2.j]]
# y is a Tensor variable with shape [2, 2, 2] and elements as below:
# [[[1, 2], [3, 4]],
# [[5, 6], [7, 8]]]
# Each example is followed by the corresponding output tensor.
y = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]) + 1j * np.array([[[4, 3], [2, 1]], [[8, 7], [6, 5]]])
y = dg.to_variable(y)
out5 = cpx.sum(y, dim=[1, 2]) # [10.+10.j, 26.+26.j]
out6 = cpx.sum(y, dim=[0, 1]) # [16.+20.j, 20.+16.j]
"""
complex_variable_exists([input], "sum")
real = math.sum(input.real, axis=dim, keepdim=keep_dim, name=name)
imag = math.sum(input.imag, axis=dim, keepdim=keep_dim, name=name)
return ComplexVariable(real, imag)
def kron(x, y, name=None):
"""
The kronecker product of two complex tensors. At least one of inputs :attr:`x`
and :attr:`y` must be a ComplexVariable. See the detailed description for
the function and other arguments in :ref:`api_paddle_tensor_kron` .
Let $x = a + ib$, and $y = c + id$, the euqation is
.. math::
kron(x, y) = kron(a, c) - kron(b, d) + i(kron(a, d) + kron(b, c))
Args:
x (Variable|ComplexVariable): The first input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
y (Variable|ComplexVariable): The second input Variable or ComplexVariable
with any number of dimensions. The supported data types include float32
and float64 when it is a Variable. Otherwise the supported data types
are complex64 or complex128.
name(str, optional): The default value is None. Normally there is no
need for user to set this property. For more information, please
refer to :ref:`api_guide_Name`.
Returns:
ComplexVariable: The kronecker product, data type: complex64 or complex128, depending on the data type of x and y. If the data types of x and y are float32/complex64, the data type of the output is complex64, else if the data types of x and y are float64/complex128, the data type of the output is complex128.
Examples:
.. code-block:: python
import numpy as np
import paddle
from paddle import fluid
import paddle.fluid.dygraph as dg
a = np.array([[1.0+1.0j, 2.0+1.0j], [3.0+1.0j, 4.0+1.0j]])
b = np.array([[5.0+2.0j, 6.0+2.0j], [7.0+2.0j, 8.0+2.0j]])
place = fluid.CPUPlace()
with dg.guard(place):
x = dg.to_variable(a)
y = dg.to_variable(b)
out = paddle.complex.kron(x, y)
print(out.numpy())
# [[ 3. +7.j 4. +8.j 8. +9.j 10.+10.j]
# [ 5. +9.j 6.+10.j 12.+11.j 14.+12.j]
# [13.+11.j 16.+12.j 18.+13.j 22.+14.j]
# [19.+13.j 22.+14.j 26.+15.j 30.+16.j]]
"""
complex_variable_exists([x, y], "kron")
# X = A + Bi, Y = C+Di
# kron(X, Y) = kron(A, C) - kron(B, D) + (kron(A, D) + kron(B, C))i
(a, b) = (x.real, x.imag) if is_complex(x) else (x, None)
(c, d) = (y.real, y.imag) if is_complex(y) else (y, None)
if is_real(b) and is_real(d):
real = math.kron(a, c) - math.kron(b, d)
imag = math.kron(a, d) + math.kron(b, c)
elif is_real(b):
real = math.kron(a, c)
imag = math.kron(b, c)
else:
# is_real(d)
real = math.kron(a, c)
imag = math.kron(a, d)
return ComplexVariable(real, imag)
# Copyright (c) 2020 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.
from __future__ import division
from ...fluid import framework
from . import tensor
def monkey_patch_math_complex():
# complexVariable do not support scaler type now, so here not contains
# reverse methods, such as "__radd__", "__rsub__", "__rmul__", "__rdiv__",
# "__rtruediv__", "__rmatmul__".
complex_methods = [
('__add__', _binary_creator_('__add__', "elementwise_add", False)),
('__sub__', _binary_creator_('__sub__', "elementwise_sub", False)),
('__mul__', _binary_creator_('__mul__', "elementwise_mul", False)),
('__div__', _binary_creator_('__div__', "elementwise_div", False)),
('__truediv__', _binary_creator_('__truediv__', "elementwise_div",
False)),
('__matmul__', _binary_creator_('__matmul__', "matmul", False)),
]
for method in complex_methods:
method_name = method[0]
method_impl = method[1]
if method_impl:
setattr(framework.ComplexVariable, method_name, method_impl)
for method in tensor.__all__:
method_impl = getattr(tensor, method)
if method_impl:
setattr(framework.ComplexVariable, method, method_impl)
# for binary operator such as elementwise
def _binary_creator_(method_name, op_type, reverse=False):
def __impl__(self, other_var):
math_op = getattr(tensor, op_type)
return math_op(self, other_var)
__impl__.__name__ = method_name
return __impl__
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册