# Copyright 2021 Huawei Technologies Co., Ltd
#
# 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.
# ============================================================================
# pylint: disable=abstract-method,import-outside-toplevel
"""Basic module for quantum gate."""
import numbers
import numpy as np
from scipy.linalg import fractional_matrix_power
from mindquantum import mqbackend as mb
from mindquantum.config.config import _GLOBAL_MAT_VALUE
from mindquantum.utils.f import is_power_of_two
from mindquantum.utils.type_value_check import _check_gate_type, _check_input_type
from ..parameterresolver import ParameterResolver
from .basic import (
BasicGate,
FunctionalGate,
NoneParamNonHermMat,
NoneParamSelfHermMat,
ParameterOppsGate,
ParamNonHerm,
PauliGate,
PauliStringGate,
RotSelfHermMat,
)
[文档]class UnivMathGate(NoneParamNonHermMat):
r"""
Universal math gate.
More usage, please see :class:`mindquantum.core.gates.XGate`.
Args:
name (str): the name of this gate.
mat (np.ndarray): the matrix value of this gate.
Examples:
>>> from mindquantum.core.gates import UnivMathGate
>>> x_mat=np.array([[0,1],[1,0]])
>>> X_gate=UnivMathGate('X',x_mat)
>>> x1=X_gate.on(0,1)
>>> print(x1)
X(0 <-: 1)
"""
def __init__(self, name, matrix_value):
"""Initialize a UnivMathGate object."""
if len(matrix_value.shape) != 2:
raise ValueError(f"matrix_value require shape of 2, but get shape of {matrix_value.shape}")
if matrix_value.shape[0] != matrix_value.shape[1]:
raise ValueError(f"matrix_value need a square matrix, but get shape {matrix_value.shape}")
if not is_power_of_two(matrix_value.shape[0]):
raise ValueError(f"Dimension of matrix_value need should be power of 2, but get {matrix_value.shape[0]}")
n_qubits = int(np.log2(matrix_value.shape[0]))
super().__init__(name=name, n_qubits=n_qubits, matrix_value=matrix_value)
[文档] def get_cpp_obj(self):
"""Get the underlying C++ object."""
mat = mb.dim2matrix(self.matrix())
cpp_gate = mb.basic_gate(False, self.name, 1, mat)
cpp_gate.daggered = self.hermitianed
cpp_gate.obj_qubits = self.obj_qubits
cpp_gate.ctrl_qubits = self.ctrl_qubits
return cpp_gate
[文档]class HGate(NoneParamSelfHermMat):
r"""
Hadamard gate.
Hadamard gate with matrix as:
.. math::
{\rm H}=\frac{1}{\sqrt{2}}\begin{pmatrix}1&1\\1&-1\end{pmatrix}
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize an HGate object."""
super().__init__(
name='H',
n_qubits=1,
matrix_value=_GLOBAL_MAT_VALUE['H'],
)
def __eq__(self, other):
"""Equality comparison operator."""
return BasicGate.__eq__(self, other)
[文档]class XGate(PauliGate):
r"""
Pauli-X gate.
Pauli X gate with matrix as:
.. math::
{\rm X}=\begin{pmatrix}0&1\\1&0\end{pmatrix}
For simplicity, we define ```X``` as a instance of ```XGate()```. For more
redefine, please refer to the functional table below.
Note:
For simplicity, you can do power operator on pauli gate (only works
for pauli gate at this time). The rule is set below as:
.. math::
X^\theta = RX(\theta\pi)
Examples:
>>> from mindquantum.core.gates import X
>>> x1 = X.on(0)
>>> cnot = X.on(0, 1)
>>> print(x1)
X(0)
>>> print(cnot)
X(0 <-: 1)
>>> x1.matrix()
array([[0, 1],
[1, 0]])
>>> x1**2
RX(2π)
>>> (x1**'a').coeff
{'a': 3.141592653589793}, const: 0.0
>>> (x1**{'a' : 2}).coeff
{'a': 6.283185307179586}, const: 0.0
"""
def __init__(self):
"""Initialize an XGate object."""
super().__init__(
name='X',
n_qubits=1,
matrix_value=_GLOBAL_MAT_VALUE['X'],
)
def __eq__(self, other):
"""Equality comparison operator."""
if isinstance(other, CNOTGate):
obj = [other.obj_qubits[0]]
ctrl = [other.obj_qubits[1]]
ctrl.extend(other.ctrl_qubits)
if self.obj_qubits == obj and set(self.ctrl_qubits) == set(ctrl):
return True
return False
return super().__eq__(other)
[文档]class YGate(PauliGate):
r"""
Pauli Y gate.
Pauli Y gate with matrix as:
.. math::
{\rm Y}=\begin{pmatrix}0&-i\\i&0\end{pmatrix}
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize a YGate object."""
super().__init__(
name='Y',
n_qubits=1,
matrix_value=_GLOBAL_MAT_VALUE['Y'],
)
[文档]class ZGate(PauliGate):
r"""
Pauli-Z gate.
Pauli Z gate with matrix as:
.. math::
{\rm Z}=\begin{pmatrix}1&0\\0&-1\end{pmatrix}
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize a ZGate object."""
super().__init__(
name='Z',
n_qubits=1,
matrix_value=_GLOBAL_MAT_VALUE['Z'],
)
[文档]class IGate(PauliGate):
r"""
Identity gate.
Identity gate with matrix as:
.. math::
{\rm I}=\begin{pmatrix}1&0\\0&1\end{pmatrix}
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize an IGate object."""
super().__init__(
name='I',
n_qubits=1,
matrix_value=_GLOBAL_MAT_VALUE['I'],
)
def __eq__(self, other):
"""Equality comparison operator."""
_check_gate_type(other)
return isinstance(other, IGate)
[文档]class CNOTGate(NoneParamSelfHermMat):
r"""
Control-X gate.
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize a CNOTGate object."""
super().__init__(
name='CNOT',
n_qubits=2,
matrix_value=_GLOBAL_MAT_VALUE['CNOT'],
)
[文档] def on(self, obj_qubits, ctrl_qubits=None):
"""
Define which qubit the gate act on and the control qubit.
Note:
In this framework, the qubit that the gate act on is specified
first, even for control gate, e.g. CNOT, the second arg is control
qubits.
Args:
obj_qubits (int, list[int]): Specific which qubits the gate act on.
ctrl_qubits (int, list[int]): Specific the control qbits. Default, None.
Returns:
Gate, Return a new gate.
"""
if ctrl_qubits is None:
raise ValueError("A control qubit is needed for CNOT gate!")
if isinstance(ctrl_qubits, (int, np.int64)):
ctrl_qubits = [ctrl_qubits]
elif not isinstance(ctrl_qubits, list) or not ctrl_qubits:
raise ValueError(f"ctrl_qubits requires a list, but get {type(ctrl_qubits)}")
return super().on([obj_qubits, ctrl_qubits[0]], ctrl_qubits[1:])
def __eq__(self, other):
"""Equality comparison operator."""
if isinstance(other, XGate):
return other.__eq__(self)
return BasicGate.__eq__(self, other)
def __decompose__(self):
"""Gate decomposition method."""
return X.on(self.obj_qubits[0], [self.obj_qubits[1], *self.ctrl_qubits]).__decompose__()
[文档]class SWAPGate(NoneParamSelfHermMat):
"""
SWAP gate that swap two different qubits.
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize a SWAPGate object."""
super().__init__(
name='SWAP',
n_qubits=2,
matrix_value=_GLOBAL_MAT_VALUE['SWAP'],
)
def __eq__(self, other):
"""Equality comparison operator."""
_check_gate_type(other)
if isinstance(other, SWAPGate):
return set(self.obj_qubits) == set(other.obj_qubits) and set(self.ctrl_qubits) == set(other.ctrl_qubits)
return False
[文档]class ISWAPGate(NoneParamNonHermMat):
r"""
ISWAP gate.
ISWAP gate that swaps two different qubits and phase the :math:`\left|01\right>` and :math:`\left|10\right>`
amplitudes by :math:`i`.
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize an ISWAPGate object."""
super().__init__(
name='ISWAP',
n_qubits=2,
matrix_value=_GLOBAL_MAT_VALUE['ISWAP'],
)
def __eq__(self, other):
"""Equality comparison operator."""
_check_gate_type(other)
if isinstance(other, ISWAPGate):
return set(self.obj_qubits) == set(other.obj_qubits) and set(self.ctrl_qubits) == set(other.ctrl_qubits)
return False
[文档]class TGate(NoneParamNonHermMat):
r"""
T gate.
T gate with matrix as :
.. math::
{\rm T}=\begin{pmatrix}1&0\\0&(1+i)/\sqrt(2)\end{pmatrix}
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize a TGate object."""
super().__init__(
name='T',
n_qubits=1,
matrix_value=_GLOBAL_MAT_VALUE['T'],
)
[文档]class SGate(NoneParamNonHermMat):
r"""
S gate.
S gate with matrix as :
.. math::
{\rm S}=\begin{pmatrix}1&0\\0&i\end{pmatrix}
More usage, please see :class:`mindquantum.core.gates.XGate`.
"""
def __init__(self):
"""Initialize an SGate object."""
super().__init__(
name='S',
n_qubits=1,
matrix_value=_GLOBAL_MAT_VALUE['S'],
)
[文档]class RX(RotSelfHermMat):
r"""
Rotation gate around x-axis.
.. math::
{\rm RX}=\begin{pmatrix}\cos(\theta/2)&-i\sin(\theta/2)\\
-i\sin(\theta/2)&\cos(\theta/2)\end{pmatrix}
The rotation gate can be initialized in three different ways.
1. If you initialize it with a single number, then it will be a non
parameterized gate with a certain rotation angle.
2. If you initialize it with a single str, then it will be a
parameterized gate with only one parameter and the default
coefficience is one.
3. If you initialize it with a dict, e.g. `{'a':1,'b':2}`, this gate
can have multiple parameters with certain coefficiences. In this case,
it can be expressed as:
.. math::
RX(a+2b)
Args:
pr (Union[int, float, str, dict, ParameterResolver]): the parameters of
parameterized gate, see above for detail explanation.
Examples:
>>> from mindquantum.core.gates import RX
>>> import numpy as np
>>> rx1 = RX(0.5)
>>> np.round(rx1.matrix(), 2)
array([[0.97+0.j , 0. -0.25j],
[0. -0.25j, 0.97+0.j ]])
>>> rx2 = RX('a')
>>> np.round(rx2.matrix({'a':0.1}), 3)
array([[0.999+0.j , 0. -0.05j],
[0. -0.05j, 0.999+0.j ]])
>>> rx3 = RX({'a' : 0.2, 'b': 0.5}).on(0, 2)
>>> print(rx3)
RX(0.2*a + 0.5*b|0 <-: 2)
>>> np.round(rx3.matrix({'a' : 1, 'b' : 2}), 2)
array([[0.83+0.j , 0. -0.56j],
[0. -0.56j, 0.83+0.j ]])
>>> np.round(rx3.diff_matrix({'a' : 1, 'b' : 2}, about_what = 'a'), 2)
array([[-0.06+0.j , 0. -0.08j],
[ 0. -0.08j, -0.06+0.j ]])
>>> rx3.coeff
{'a': 0.2, 'b': 0.5}
"""
def __init__(self, pr):
"""Initialize an RX gate."""
super().__init__(
pr=ParameterResolver(pr),
name='RX',
n_qubits=1,
core=XGate(),
)
[文档]class RY(RotSelfHermMat):
r"""
Rotation gate around y-axis. More usage, please see :class:`mindquantum.core.gates.RX`.
.. math::
{\rm RY}=\begin{pmatrix}\cos(\theta/2)&-\sin(\theta/2)\\
\sin(\theta/2)&\cos(\theta/2)\end{pmatrix}
Args:
pr (Union[int, float, str, dict, ParameterResolver]): the parameters of
parameterized gate, see above for detail explanation.
"""
def __init__(self, pr):
"""Initialize an RY object."""
super().__init__(
pr=ParameterResolver(pr),
name='RY',
n_qubits=1,
core=YGate(),
)
[文档]class RZ(RotSelfHermMat):
r"""
Rotation gate around z-axis. More usage, please see :class:`mindquantum.core.gates.RX`.
.. math::
{\rm RZ}=\begin{pmatrix}\exp(-i\theta/2)&0\\
0&\exp(i\theta/2)\end{pmatrix}
Args:
pr (Union[int, float, str, dict, ParameterResolver]): the parameters of
parameterized gate, see above for detail explanation.
"""
def __init__(self, pr):
"""Initialize an RZ object."""
super().__init__(
pr=ParameterResolver(pr),
name='RZ',
n_qubits=1,
core=ZGate(),
)
[文档]class ZZ(RotSelfHermMat):
r"""
Ising ZZ gate. More usage, please see :class:`mindquantum.core.gates.RX`.
.. math::
{\rm ZZ_\theta}=\cos(\theta)I\otimes I-i\sin(\theta)\sigma_Z\otimes\sigma_Z
Args:
pr (Union[int, float, str, dict, ParameterResolver]): the parameters of
parameterized gate, see above for detail explanation.
"""
def __init__(self, pr):
"""Initialize a ZZ object."""
super().__init__(
pr=ParameterResolver(pr),
name='ZZ',
n_qubits=2,
core=PauliStringGate([Z, Z]),
)
def __decompose__(self):
"""Gate decomposition method."""
from ..circuit import Circuit # pylint: disable=cyclic-import
out = []
out.append(Circuit())
out[-1] += X.on(self.obj_qubits[0], [self.obj_qubits[1], *self.ctrl_qubits])
out[-1] += RZ(2 * self.coeff).on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[0], [self.obj_qubits[1], *self.ctrl_qubits])
out.append(Circuit())
out[-1] += X.on(self.obj_qubits[1], [self.obj_qubits[0], *self.ctrl_qubits])
out[-1] += RZ(2 * self.coeff).on(self.obj_qubits[1], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[1], [self.obj_qubits[0], *self.ctrl_qubits])
return out
[文档] def matrix(self, pr=None, frac=1):
"""
Get the matrix of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
frac (numbers.Number): The multiple of the coefficient. Default: 1.
Returns:
numpy.ndarray, the matrix of this gate.
"""
return super().matrix(pr, frac)
[文档] def diff_matrix(self, pr=None, about_what=None, frac=1):
"""
Differential form of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
about_what (str): calculate the gradient w.r.t which parameter. Default: None.
frac (numbers.Number): The multiple of the coefficient. Default: 1.
Returns:
numpy.ndarray, the differential form matrix.
"""
return super().diff_matrix(pr, about_what, 1)
[文档]class XX(RotSelfHermMat):
r"""
Ising XX gate. More usage, please see :class:`mindquantum.core.gates.RX`.
.. math::
{\rm XX_\theta}=\cos(\theta)I\otimes I-i\sin(\theta)\sigma_x\otimes\sigma_x
Args:
pr (Union[int, float, str, dict, ParameterResolver]): the parameters of
parameterized gate, see above for detail explanation.
"""
def __init__(self, pr):
"""Initialize an XX object."""
super().__init__(
pr=ParameterResolver(pr),
name='XX',
n_qubits=2,
core=PauliStringGate([X, X]),
)
def __decompose__(self):
"""Gate decomposition method."""
from ..circuit import Circuit # pylint: disable=cyclic-import
out = []
out.append(Circuit())
out[-1] += H.on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += H.on(self.obj_qubits[1], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[0], [self.obj_qubits[1], *self.ctrl_qubits])
out[-1] += RZ(2 * self.coeff).on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[0], [self.obj_qubits[1], *self.ctrl_qubits])
out[-1] += H.on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += H.on(self.obj_qubits[1], [*self.ctrl_qubits])
out.append(Circuit())
out[-1] += H.on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += H.on(self.obj_qubits[1], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[1], [self.obj_qubits[0], *self.ctrl_qubits])
out[-1] += RZ(2 * self.coeff).on(self.obj_qubits[1], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[1], [self.obj_qubits[0], *self.ctrl_qubits])
out[-1] += H.on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += H.on(self.obj_qubits[1], [*self.ctrl_qubits])
return out
[文档] def matrix(self, pr=None, frac=1):
"""
Get the matrix of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
frac (numbers.Number): The multiple of the coefficient. Default: 1.
Returns:
numpy.ndarray, the matrix of this gate.
"""
return super().matrix(pr, 1)
[文档] def diff_matrix(self, pr=None, about_what=None, frac=1):
"""
Differential form of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
about_what (str): calculate the gradient w.r.t which parameter. Default: None.
frac (numbers.Number): The multiple of the coefficient. Default: 1.
Returns:
numpy.ndarray, the differential form matrix.
"""
return super().diff_matrix(pr, about_what, 1)
[文档]class YY(RotSelfHermMat):
r"""
Ising YY gate. More usage, please see :class:`mindquantum.core.gates.RX`.
.. math::
{\rm YY_\theta}=\cos(\theta)I\otimes I-i\sin(\theta)\sigma_y\otimes\sigma_y
Args:
pr (Union[int, float, str, dict, ParameterResolver]): the parameters of
parameterized gate, see above for detail explanation.
"""
def __init__(self, pr):
"""Initialize an YY object."""
super().__init__(
pr=ParameterResolver(pr),
name='YY',
n_qubits=2,
core=PauliStringGate([Y, Y]),
)
def __decompose__(self):
"""Gate decomposition method."""
from ..circuit import Circuit # pylint: disable=cyclic-import
out = []
out.append(Circuit())
out[-1] += RX(np.pi / 2).on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += RX(np.pi / 2).on(self.obj_qubits[1], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[0], [self.obj_qubits[1], *self.ctrl_qubits])
out[-1] += RZ(2 * self.coeff).on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[0], [self.obj_qubits[1], *self.ctrl_qubits])
out[-1] += RX(7 * np.pi / 2).on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += RX(7 * np.pi / 2).on(self.obj_qubits[1], [*self.ctrl_qubits])
out.append(Circuit())
out[-1] += RX(np.pi / 2).on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += RX(np.pi / 2).on(self.obj_qubits[1], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[1], [self.obj_qubits[0], *self.ctrl_qubits])
out[-1] += RZ(2 * self.coeff).on(self.obj_qubits[1], [*self.ctrl_qubits])
out[-1] += X.on(self.obj_qubits[1], [self.obj_qubits[0], *self.ctrl_qubits])
out[-1] += RX(7 * np.pi / 2).on(self.obj_qubits[0], [*self.ctrl_qubits])
out[-1] += RX(7 * np.pi / 2).on(self.obj_qubits[1], [*self.ctrl_qubits])
return out
[文档] def matrix(self, pr=None, frac=1):
"""
Get the matrix of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
frac (numbers.Number): The multiple of the coefficient. Default: 1.
Returns:
numpy.ndarray, the matrix of this gate.
"""
return super().matrix(pr, 1)
[文档] def diff_matrix(self, pr=None, about_what=None, frac=1):
"""
Differential form of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
about_what (str): calculate the gradient w.r.t which parameter. Default: None.
frac (numbers.Number): The multiple of the coefficient. Default: 1.
Returns:
numpy.ndarray, the differential form matrix.
"""
return super().diff_matrix(pr, about_what, 1)
[文档]class BarrierGate(FunctionalGate):
"""
Barrier gate do nothing but set a barrier for drawing circuit.
The system will not draw quantum gates around barrier gate.
Args:
show (bool): whether show the barrier gate. Default: True.
"""
def __init__(self, show=True):
"""Initialize a BarrierGate object."""
super().__init__(name='BARRIER', n_qubits=0)
self.show = show
[文档] def on(self, obj_qubits, ctrl_qubits=None):
"""
Define which qubit the gate act on and the control qubit.
Note:
This implementation will always raise a runtime error since this is not supported with BarrierGate objects.
Args:
obj_qubits (int, list[int]): Specific which qubits the gate act on.
ctrl_qubits (int, list[int]): Specific the control qbits. Default, None.
Returns:
Gate, Return a new gate.
"""
raise RuntimeError("Cannot call on for BarrierGate.")
[文档]class GlobalPhase(RotSelfHermMat):
r"""
Global phase gate. More usage, please see :class:`mindquantum.core.gates.RX`.
.. math::
{\rm GlobalPhase}=\begin{pmatrix}\exp(-i\theta)&0\\
0&\exp(-i\theta)\end{pmatrix}
Args:
pr (Union[int, float, str, dict, ParameterResolver]): the parameters of
parameterized gate, see above for detail explanation.
"""
def __init__(self, pr):
"""Initialize a GlobalPhase object."""
super().__init__(
pr=ParameterResolver(pr),
name='GP',
n_qubits=1,
core=IGate(),
)
[文档] def matrix(self, pr=None, **kwargs): # pylint: disable=arguments-differ,unused-argument
"""
Matrix of parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
kwargs (dict): other key arguments.
Returns:
numpy.ndarray, the matrix of this gate.
"""
return RotSelfHermMat.matrix(self, pr, 1)
[文档] def diff_matrix(self, pr=None, about_what=None, **kwargs): # pylint: disable=arguments-differ,unused-argument
"""
Differential form of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
about_what (str): calculate the gradient w.r.t which parameter. Default: None.
kwargs (dict): othet key arguments.
Returns:
numpy.ndarray, the differential form matrix.
"""
return RotSelfHermMat.diff_matrix(self, pr, about_what, 1)
BARRIER = BarrierGate(show=False)
[文档]class PhaseShift(ParameterOppsGate):
r"""
Phase shift gate. More usage, please see :class:`mindquantum.core.gates.RX`.
.. math::
{\rm PhaseShift}=\begin{pmatrix}1&0\\
0&\exp(i\theta)\end{pmatrix}
Args:
pr (Union[int, float, str, dict, ParameterResolver]): the parameters of
parameterized gate, see above for detail explanation.
"""
def __init__(self, pr):
"""Initialize a PhaseShift object."""
super().__init__(
pr=ParameterResolver(pr),
name='PS',
n_qubits=1,
)
# pylint: disable=arguments-differ
[文档] def matrix(self, pr=None):
"""
Get the matrix of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
Returns:
numpy.ndarray, the matrix of this gate.
"""
val = 0
if self.coeff.is_const():
val = self.coeff.const
else:
new_pr = self.coeff.combination(pr)
if not new_pr.is_const():
raise ValueError("The parameter is not set completed.")
val = new_pr.const
return np.array([[1, 0], [0, np.exp(1j * val)]])
[文档] def diff_matrix(self, pr=None, about_what=None):
"""
Differential form of this parameterized gate.
Args:
pr (Union[ParameterResolver, dict]): The parameter value for parameterized gate. Default: None.
about_what (str): calculate the gradient w.r.t which parameter.
Returns:
numpy.ndarray, the differential form matrix.
"""
if self.coeff.is_const():
return np.zeros((2, 2))
new_pr = self.coeff.combination(pr)
if not new_pr.is_const():
raise ValueError("The parameter is not set completed.")
val = new_pr.const
if about_what is None:
if len(self.coeff) != 1:
raise ValueError("Should specific which parameter are going to do derivation.")
for i in self.coeff:
about_what = i
return np.array([[0, 0], [0, 1j * self.coeff[about_what] * np.exp(1j * val)]])
[文档]class Power(NoneParamNonHermMat):
r"""
Power operator on a non parameterized gate.
Args:
gates (:class:`mindquantum.core.gates.NoneParameterGate`): The basic gate you need to apply power operator.
exponent (int, float): The exponenet. Default: 0.5.
Examples:
>>> from mindquantum.core.gates import Power
>>> import numpy as np
>>> rx1 = RX(0.5)
>>> rx2 = RX(1)
>>> assert np.all(np.isclose(Power(rx2,0.5).matrix(), rx1.matrix()))
"""
def __init__(self, gate, exponent=0.5):
"""Initialize a Power object."""
_check_input_type('t', numbers.Number, exponent)
name = f'{gate}^{exponent}'
n_qubits = gate.n_qubits
matrix_value = fractional_matrix_power(gate.matrix(), exponent)
super().__init__(
name=name,
n_qubits=n_qubits,
matrix_value=matrix_value,
)
self.gate = gate
self.t = exponent # pylint: disable=invalid-name
[文档] def get_cpp_obj(self):
"""Get the underlying C++ object."""
mat = mb.dim2matrix(self.matrix())
cpp_gate = mb.basic_gate(False, self.name, 1, mat)
cpp_gate.daggered = self.hermitianed
cpp_gate.obj_qubits = self.obj_qubits
cpp_gate.ctrl_qubits = self.ctrl_qubits
return cpp_gate
def __eq__(self, other):
"""Equality comparison operator."""
_check_gate_type(other)
if self.obj_qubits == other.obj_qubits and set(self.ctrl_qubits) == set(other.ctrl_qubits):
if self.gate == other and self.t == 1:
return True
if isinstance(other, Power):
if self.gate == other.gate and self.t == other.t:
return True
return False
[文档]def gene_univ_parameterized_gate(name, matrix_generator, diff_matrix_generator):
"""
Generate a customer parameterized gate based on the single parameter defined unitary matrix.
Args:
name (str): The name of this gate.
matrix_generator (Union[FunctionType, MethodType]): A function or a method that
take exactly one argument to generate a unitary matrix.
diff_matrix_generator (Union[FunctionType, MethodType]): A function or a method
that take exactly one argument to generate the derivative of this unitary matrix.
Returns:
_ParamNonHerm, a customer parameterized gate.
Examples:
>>> import numpy as np
>>> from mindquantum.core.circuit import Circuit
>>> from mindquantum.core.gates import gene_univ_parameterized_gate
>>> from mindquantum.simulator import Simulator
>>> def matrix(theta):
... return np.array([[np.exp(1j * theta), 0],
... [0, np.exp(-1j * theta)]])
>>> def diff_matrix(theta):
... return 1j*np.array([[np.exp(1j * theta), 0],
... [0, -np.exp(-1j * theta)]])
>>> TestGate = gene_univ_parameterized_gate('Test', matrix, diff_matrix)
>>> circ = Circuit().h(0)
>>> circ += TestGate('a').on(0)
>>> circ
q0: ──H────Test(a)──
>>> circ.get_qs(pr={'a': 1.2})
array([0.25622563+0.65905116j, 0.25622563-0.65905116j])
"""
matrix = matrix_generator(0)
n_qubits = int(np.log2(matrix.shape[0]))
class _ParamNonHerm(ParamNonHerm):
"""The customer parameterized gate."""
def __init__(self, pr):
super().__init__(
pr=ParameterResolver(pr),
name=name,
n_qubits=n_qubits,
matrix_generator=matrix_generator,
diff_matrix_generator=diff_matrix_generator,
)
def get_cpp_obj(self):
if not self.hermitianed:
cpp_gate = mb.basic_gate(self.name, 1, self.matrix_generator, self.diff_matrix_generator)
else:
cpp_gate = mb.basic_gate(
self.name,
1,
lambda x: np.conj(self.matrix_generator(x).T),
lambda x: np.conj(self.diff_matrix_generator(x).T),
)
cpp_gate.daggered = self.hermitianed
cpp_gate.obj_qubits = self.obj_qubits
cpp_gate.ctrl_qubits = self.ctrl_qubits
if not self.parameterized:
cpp_gate.apply_value(self.coeff.const)
else:
cpp_gate.params = self.coeff.get_cpp_obj()
return cpp_gate
return _ParamNonHerm
X = XGate()
Y = YGate()
Z = ZGate()
I = IGate() # noqa: E741
H = HGate()
T = TGate()
S = SGate()
CNOT = CNOTGate()
ISWAP = ISWAPGate()
SWAP = SWAPGate()