提交 2ac9f371 编写于 作者: Q Quleaf

update to v2.2.2

上级 9a5ad8a6
......@@ -33,7 +33,7 @@ English | [简体中文](README_CN.md)
</a>
<!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v2.2.1-orange.svg?style=flat-square&logo=pypi"/>
<img src="https://img.shields.io/badge/pypi-v2.2.2-orange.svg?style=flat-square&logo=pypi"/>
</a>
<!-- Python -->
<a href="https://www.python.org/">
......@@ -152,6 +152,9 @@ We provide tutorials covering quantum simulation, machine learning, combinatoria
9. [Simulate the Spin Dynamics on a Heisenberg Chain](./tutorials/quantum_simulation/SimulateHeisenberg_EN.ipynb)
10. [Distributed Variational Quantum Eigensolver Based on Schmidt Decomposition](./tutorials/quantum_simulation/DistributedVQE_EN.ipynb)
11. [Quantum Signal Processing and Quantum Singular Value Transformation](./tutorials/quantum_simulation/QSP_and_QSVT_EN.ipynb)
12. [Hamiltonian Simulation with qDRIFT](./tutorials/quantum_simulation/QDRIFT_EN.ipynb)
13. [Quantum Phase Processing](./tutorials/quantum_simulation/QPP_EN.ipynb)
14. [Variational Quantum Metrology](./tutorials/quantum_simulation/VariationalQM_EN.ipynb)
- [Machine Learning](./tutorials/machine_learning)
1. [Encoding Classical Data into Quantum States](./tutorials/machine_learning/DataEncoding_EN.ipynb)
......@@ -163,6 +166,7 @@ We provide tutorials covering quantum simulation, machine learning, combinatoria
7. [Variational Quantum Singular Value Decomposition (VQSVD)](./tutorials/machine_learning/VQSVD_EN.ipynb)
8. [Data Encoding Analysis](./tutorials/machine_learning/EncodingAnalysis_EN.ipynb)
9. [Quantum Neural Network Approximating Functions](./tutorials/machine_learning/QApproximating_EN.ipynb)
10. [Variational quantum amplitude estimation](./tutorials/machine_learning/VQAE_EN.ipynb)
- [Combinatorial Optimization](./tutorials/combinatorial_optimization)
1. [Quantum Approximation Optimization Algorithm (QAOA)](./tutorials/combinatorial_optimization/QAOA_EN.ipynb)
......
......@@ -34,7 +34,7 @@
</a>
<!-- PyPI -->
<a href="https://pypi.org/project/paddle-quantum/">
<img src="https://img.shields.io/badge/pypi-v2.2.1-orange.svg?style=flat-square&logo=pypi"/>
<img src="https://img.shields.io/badge/pypi-v2.2.2-orange.svg?style=flat-square&logo=pypi"/>
</a>
<!-- Python -->
<a href="https://www.python.org/">
......@@ -75,7 +75,7 @@
### 安装 Paddle Quantum
我们推荐通过 `pip` 完成安装,
我们推荐通过 `pip` 完成安装
```bash
pip install paddle-quantum
......@@ -161,6 +161,9 @@ Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为
9. [模拟一维海森堡链的自旋动力学](./tutorials/quantum_simulation/SimulateHeisenberg_CN.ipynb)
10. [基于施密特分解的分布式变分量子本征求解器](./tutorials/quantum_simulation/DistributedVQE_CN.ipynb)
11. [量子信号处理与量子奇异值变换](./tutorials/quantum_simulation/QSP_and_QSVT_CN.ipynb)
12. [利用 qDRIFT 模拟时间演化](./tutorials/quantum_simulation/QDRIFT_CN.ipynb)
13. [量子相位处理](./tutorials/quantum_simulation/QPP_CN.ipynb)
14. [变分量子精密测量](./tutorials/quantum_simulation/VariationalQM_CN.ipynb)
- [机器学习](./tutorials/machine_learning)
......@@ -173,6 +176,7 @@ Paddle Quantum(量桨)建立起了人工智能与量子计算的桥梁,为
7. [变分量子奇异值分解(VQSVD)](./tutorials/machine_learning/VQSVD_CN.ipynb)
8. [数据编码分析](./tutorials/machine_learning/EncodingAnalysis_CN.ipynb)
9. [量子神经网络模拟函数](./tutorials/machine_learning/QApproximating_CN.ipynb)
10. [变分量子振幅估算](./tutorials/machine_learning/VQAE_CN.ipynb)
- [组合优化](./tutorials/combinatorial_optimization)
1. [量子近似优化算法(QAOA)](./tutorials/combinatorial_optimization/QAOA_CN.ipynb)
......
......@@ -19,7 +19,9 @@
paddle_quantum.hamiltonian
paddle_quantum.linalg
paddle_quantum.qinfo
paddle_quantum.qml
paddle_quantum.shadow
paddle_quantum.trotter
paddle_quantum.visual
paddle_quantum.qsvt
\ No newline at end of file
paddle_quantum.qsvt
paddle_quantum.qpp
......@@ -13,3 +13,4 @@ paddle\_quantum.gate.functional
paddle_quantum.gate.functional.base
paddle_quantum.gate.functional.multi_qubit_gate
paddle_quantum.gate.functional.single_qubit_gate
paddle_quantum.gate.functional.visual
\ No newline at end of file
paddle\_quantum.gate.functional.base
===========================================
.. automodule:: paddle_quantum.gate.functional.visual
:members:
:show-inheritance:
paddle\_quantum.qml
============================
.. automodule:: paddle_quantum.qml
:members:
:undoc-members:
:show-inheritance:
.. rubric:: Submodules
.. toctree::
:maxdepth: 4
paddle_quantum.qml.vsql
paddle\_quantum.qml.vsql
==================================
.. automodule:: paddle_quantum.qml.vsql
:members:
:undoc-members:
:show-inheritance:
paddle\_quantum.qpp.angles
============================
.. automodule:: paddle_quantum.qpp.angles
:members:
:undoc-members:
:show-inheritance:
\ No newline at end of file
paddle\_quantum.qpp.laurent
============================
.. automodule:: paddle_quantum.qpp.laurent
:members:
:undoc-members:
:show-inheritance:
\ No newline at end of file
paddle\_quantum.qpp
============================
.. automodule:: paddle_quantum.qpp
:members:
:undoc-members:
:show-inheritance:
.. rubric:: Submodules
.. toctree::
:maxdepth: 4
paddle_quantum.qpp.angles
paddle_quantum.qpp.laurent
paddle_quantum.qpp.utils
\ No newline at end of file
paddle\_quantum.qpp.qpp.utils
=============================
.. automodule:: paddle_quantum.qpp.utils
:members:
:undoc-members:
:show-inheritance:
\ No newline at end of file
......@@ -19,7 +19,9 @@
paddle_quantum.hamiltonian
paddle_quantum.linalg
paddle_quantum.qinfo
paddle_quantum.qml
paddle_quantum.shadow
paddle_quantum.trotter
paddle_quantum.visual
paddle_quantum.qsvt
paddle_quantum.qpp
......@@ -28,10 +28,6 @@ paddle\_quantum.ansatz.circuit
展平后的电路参数梯度。
.. py:property:: depth()
电路深度
.. py:method:: update_param(theta, idx=None)
替换单层或所有的电路参数。
......@@ -98,6 +94,27 @@ paddle\_quantum.ansatz.circuit
:param depth: 层数,默认为 ``1``。
:type depth: int, optional
.. py:method:: sdg(qubits_idx='full', num_qubits=None, depth=1)
添加单量子比特 S dagger (逆S)门。
其矩阵形式为:
.. math::
S ^\dagger =
\begin{bmatrix}
1 & 0\ \
0 & -i
\end{bmatrix}
:param qubits_idx: 作用在的量子比特的编号,默认为 ``'full'``。
:type qubits_idx: Union[Iterable[int], int, str], optional
:param num_qubits: 总共的量子比特数量,默认为 ``None``。
:type num_qubits: int, optional
:param depth: 层数,默认为 ``1``。
:type depth: int, optional
.. py:method:: t(qubits_idx='full', num_qubits=None, depth=1)
添加单量子比特 T 门。
......@@ -118,7 +135,28 @@ paddle\_quantum.ansatz.circuit
:type num_qubits: int, optional
:param depth: 层数,默认为 ``1``。
:type depth: int, optional
.. py:method:: tdg(qubits_idx='full', num_qubits=None, depth=1)
添加单量子比特 T dagger (逆T)门。
其矩阵形式为:
.. math::
T ^\dagger =
\begin{bmatrix}
1 & 0\ \
0 & e^\frac{i\pi}{4}
\end{bmatrix}
:param qubits_idx: 作用在的量子比特的编号,默认为 ``'full'``。
:type qubits_idx: Union[Iterable[int], int, str], optional
:param num_qubits: 总共的量子比特数量,默认为 ``None``。
:type num_qubits: int, optional
:param depth: 层数,默认为 ``1``。
:type depth: int, optional
.. py:method:: x(qubits_idx='full', num_qubits=None, depth=1)
添加单量子比特 X 门。
......@@ -767,7 +805,7 @@ paddle\_quantum.ansatz.circuit
:param param_sharing: 同一层中的量子门是否共享参数,默认为 ``False``。
:type param_sharing: bool, optional
.. py:method:: oracle(oracle, qubits_idx, num_qubits=None, depth=1)
.. py:method:: oracle(oracle, qubits_idx, num_qubits=None, depth=1, gate_name='0', latex_name=None, plot_width=None)
添加一个 oracle 门。
......@@ -781,8 +819,12 @@ paddle\_quantum.ansatz.circuit
:type depth: int, optional
:param gate_name: oracle 的名字,默认为 ``O``。
:type gate_name: str, optional
:param latex_name: oracle 的Latex名字,默认为 None, 此时用 gate_name。
:type latex_name: str, optional
:param plot_width: 电路图中此门的宽度,默认为None,此时与门名称成比例。
:type gate_name: float, optional
.. py:method:: control_oracle(oracle, qubits_idx, num_qubits=None, depth=1)
.. py:method:: control_oracle(oracle, qubits_idx, num_qubits=None, depth=1, gate_name='0', latex_name=None, plot_width=None)
添加一个受控 oracle 门。
......@@ -796,6 +838,10 @@ paddle\_quantum.ansatz.circuit
:type depth: int, optional
:param gate_name: oracle 的名字,默认为 ``cO``。
:type gate_name: str, optional
:param latex_name: oracle 的Latex名字,默认为 None, 此时用 gate_name。
:type latex_name: str, optional
:param plot_width: 电路图中此门的宽度,默认为None,此时与门名称成比例。
:type gate_name: float, optional
.. py:method:: collapse(qubits_idx='full', num_qubits=None, desired_result=None, if_print=False, measure_basis='z')
......@@ -936,13 +982,13 @@ paddle\_quantum.ansatz.circuit
:param num_qubits: 总的量子比特个数,默认为 ``None``。
:type num_qubits: int, optional
.. py:method:: generalized_amplitude_damping(gamma, qubits_idx='full', num_qubits=None)
.. py:method:: generalized_amplitude_damping(gamma, prob, qubits_idx='full', num_qubits=None)
添加广义振幅阻尼信道。
:param gamma: 减振概率。
:param gamma: 减振概率,其值应该在 :math:`[0, 1]` 区间内
:type prob: Union[paddle.Tensor, float]
:param prob: 激发概率。
:param prob: 激发概率,其值应该在 :math:`[0, 1]` 区间内
:type prob: Union[paddle.Tensor, float]
:param qubits_idx: 作用在的量子比特的编号, 默认为 ``'full'``。
:type qubits_idx: Union[Iterable[int], int, str], optional
......@@ -1006,6 +1052,17 @@ paddle\_quantum.ansatz.circuit
:param num_qubits: 总的量子比特个数,默认为 ``None``。
:type num_qubits: int, optional
.. py:method:: mixed_unitary_channel(num_unitary, qubits_idx='full', num_qubits=None)
添加混合酉矩阵信道
:param num_unitary: 用于构成信道的酉矩阵的数量。
:type num_unitary: Union[paddle.Tensor, Iterable[int]]
:param qubits_idx: 作用在的量子比特的编号, 默认为 ``'full'``。
:type qubits_idx: Union[Iterable[int], int, str], optional
:param num_qubits: 总的量子比特个数,默认为 ``None``。
:type num_qubits: int, optional
.. py:method:: kraus_repr(kraus_oper, qubits_idx, num_qubits=None)
添加一个 Kraus 表示的自定义量子信道。
......@@ -1040,3 +1097,34 @@ paddle\_quantum.ansatz.circuit
:return: 每个比特上的量子门的插入历史
:rtype: List[List[Tuple[Dict[str, Union[str, List[int], paddle.Tensor]], int]]]
.. py:method:: plot(save_path, dpi=100, show=True, output=False, scale=1.0, tex=False)
画出量子电路图
:param save_path: 图像保存的路径,默认为 ``None``。
:type save_path: str, optional
:param dpi: 每英寸像素数,这里指分辨率, 默认为 `100`。
:type dpi: int, optional
:param show: 是否执行 ``plt.show()``, 默认为 ``True``。
:type show: bool, optional
:param output: 是否返回 ``matplotlib.figure.Figure`` 实例,默认为 ``False``。
:type output: bool, optional
:param scale: ``figure`` 的 ``scale`` 系数,默认为 `1.0`。
:type scale: float, optional
:param tex: 一个布尔变量,用于控制是否使用 TeX 字体,默认为 ``False``。
:type tex: bool, optional
:return: 根据 ``output`` 参数返回 ``matplotlib.figure.Figure`` 实例或 ``None``。
:rtype: Union[None, matplotlib.figure.Figure]
.. note::
使用 ``plt.show()`` 或许会导致一些问题,但是在保存图片时不会发生。如果电路太深可能会有一些图形无法显示。如果设置 ``tex = True`` 则需要在你的系统上安装 TeX 及其相关的依赖包。更多细节参考 https://matplotlib.org/stable/gallery/text_labels_and_annotations/tex_demo.html
.. py:method:: extend(cir)
量子电路扩展
:param cir: 量子电路。
:type cir: Circuit
\ No newline at end of file
......@@ -3,6 +3,21 @@ paddle\_quantum.ansatz.vans
可变结构电路的功能实现。
.. py:function:: cir_decompose(cir)
将电路中的 Layer 分解成量子门, 如果需要的话可以把所有参数门的输入转为可训练参数
:param cir: 待分解电路
:type cir: Circuit
:param trainable: 是否将分解后的参数量子门输入转为参数baidu
:type trainable: bool, optional
:return: 分解后的电路
:rtype: Circuit
.. note::
该量子电路稳定支持原生门,不支持 oracle 等其他自定义量子门。
.. py:class:: Inserter
基类: :py:class:`object`
......@@ -39,21 +54,6 @@ paddle\_quantum.ansatz.vans
:return: 简化后的电路。
:rtype: Circuit
.. py:function:: cir_decompose(cir)
将电路中的 Layer 分解成量子门, 如果需要的话可以把所有参数门的输入转为可训练参数
:param cir: 待分解电路
:type cir: Circuit
:param trainable: 是否将分解后的参数量子门输入转为参数
:type trainable: bool, optional
:return: 分解后的电路
:rtype: Circuit
.. note::
该量子电路稳定支持原生门,不支持 oracle 等其他自定义量子门。
.. py:class:: VAns(n, loss_func, *loss_func_args, epsilon=0.1, insert_rate=2, iter=100, iter_out=10, LR =0.1, threshold=0.002, accept_wall=100, zero_init_state=True)
基类: :py:class:`object`
......
......@@ -157,10 +157,10 @@ paddle\_quantum.channel.common
.. math::
E_0 = \sqrt{1-p} I,
E_1 = \sqrt{p/3} X,
E_2 = \sqrt{p/3} Y,
E_3 = \sqrt{p/3} Z.
E_0 = \sqrt{1-3p/4} I,
E_1 = \sqrt{p/4} X,
E_2 = \sqrt{p/4} Y,
E_3 = \sqrt{p/4} Z.
:param prob: 该信道的参数,其值应该在 :math:`[0, 1]` 区间内。
:type prob: Union[paddle.Tensor, float]
......@@ -169,6 +169,11 @@ paddle\_quantum.channel.common
:param num_qubits: 总的量子比特个数,默认为 ``None``。
:type num_qubits: int, optional
.. note::
该功能的实现逻辑已更新。
当前版本请参考 M.A.Nielsen and I.L.Chuang 所著 Quantum Computation and Quantum Information 第10版中的 (8.102) 式。
参考文献: Nielsen, M., & Chuang, I. (2010). Quantum Computation and Quantum Information: 10th Anniversary Edition. Cambridge: Cambridge University Press. doi:10.1017/CBO9780511976667
.. py:class:: PauliChannel(prob, qubits_idx='full', num_qubits)
基类::py:class:`paddle_quantum.channel.base.Channel`
......@@ -249,3 +254,16 @@ paddle\_quantum.channel.common
.. note::
时间常数必须满足 :math:`T_2 \le T_1`,见参考文献 https://arxiv.org/abs/2101.02109。
.. py:class:: MixedUnitaryChannel(num_unitary, qubits_idx='full', num_qubits=None)
基类::py:class:`paddle_quantum.channel.base.Channel`
混合酉矩阵信道。
:param num_unitary: 用于构成信道的酉矩阵数量。
:type num_unitary: int
:param qubits_idx: 作用在的量子比特的编号,默认为 ``'full'``。
:type qubits_idx: Union[Iterable[int], int, str], optional
:param num_qubits: 总的量子比特个数,默认为 ``None``。
:type num_qubits: int, optional
\ No newline at end of file
......@@ -24,6 +24,29 @@ paddle\_quantum.gate.base
生成量子门的历史记录
.. py:method:: set_gate_info(**kwargs)
设置 `gate_info` 的接口
:param kwargs: 用于设置 `gate_info` 的参数。
:type kwargs: Any
.. py:method:: display_in_circuit(ax, x)
画出量子电路图,在 `Circuit` 类中被调用。
:param ax: ``matplotlib.axes.Axes`` 的实例.
:type ax: matplotlib.axes.Axes
:param x: 开始的水平位置。
:type x: float
:return: 占用的总宽度。
:rtype: float
.. note::
使用者可以覆写此函数,从而自定义显示方式。
.. py:class:: ParamGate
基类::py:class:`paddle_quantum.gate.base.Gate`
......
......@@ -11,3 +11,4 @@ paddle\_quantum.gate.functional
paddle_quantum.gate.functional.base
paddle_quantum.gate.functional.multi_qubit_gate
paddle_quantum.gate.functional.single_qubit_gate
paddle_quantum.gate.functional.visual
......@@ -33,6 +33,21 @@ paddle\_quantum.gate.functional.single\_qubit\_gate
:return: 输出态。
:rtype: paddle_quantum.State
.. py:function:: sdg(state, qubit_idx, dtype, backend)
在输入态上作用一个S dagger(逆S)门。
:param state: 输入态。
:type state: paddle_quantum.State
:param qubit_idx: 作用在量子比特的编号。
:type qubit_idx: int
:param dtype: 数据的类型。
:type dtype: str
:param backend: 运行模拟的后端。
:type backend: paddle_quantum.Backend
:return: 输出态。
:rtype: paddle_quantum.State
.. py:function:: t(state, qubit_idx, dtype, backend)
在输入态上作用一个 T 门。
......@@ -48,6 +63,21 @@ paddle\_quantum.gate.functional.single\_qubit\_gate
:return: 输出态。
:rtype: paddle_quantum.State
.. py:function:: tdg(state, qubit_idx, dtype, backend)
在输入态上作用一个T dagger(逆T)门。
:param state: 输入态。
:type state: paddle_quantum.State
:param qubit_idx: 作用在量子比特的编号。
:type qubit_idx: int
:param dtype: 数据的类型。
:type dtype: str
:param backend: 运行模拟的后端。
:type backend: paddle_quantum.Backend
:return: 输出态。
:rtype: paddle_quantum.State
.. py:function:: x(state, qubit_idx, dtype, backend)
在输入态上作用一个 X 门。
......
paddle\_quantum.gate.functional.visual
=======================================
可视化 ``paddle_quantum.ansatz.Circuit`` 类中量子门的函数
.. py:function:: scale_circuit_plot_param(scale)
根据 ``scale`` 修改 ``__CIRCUIT_PLOT_PARAM`` 的字典参数。
:param scale: 画图参数的缩放标量。
:type scale: float
.. py:function:: set_circuit_plot_param(**kwargs)
自定义画图参数字典 ``__CIRCUIT_PLOT_PARAM``。
:param kwargs: 需要更新的字典 ``__CIRCUIT_PLOT_PARAM`` 参数。
:type scale: Any
.. py:function:: get_circuit_plot_param()
输出画图参数字典 ``__CIRCUIT_PLOT_PARAM``。
:return: ``__CIRCUIT_PLOT_PARAM`` 字典的拷贝。
:rtype: dict
.. py:function:: reset_circuit_plot_param()
重置画图参数字典 ``__CIRCUIT_PLOT_PARAM``。
......@@ -140,7 +140,7 @@ paddle\_quantum.gate.layer
:param depth: 层数,默认为 ``1``。
:type depth: int, optional
.. py:class:: QAOALayer(Gate)
.. py:class:: QAOALayerWeighted(Gate)
基类::py:class:`paddle_quantum.gate.base.Gate`
......
......@@ -49,6 +49,29 @@ paddle\_quantum.gate.single\_qubit\_gate
:param depth: 层数,默认为 ``1``。
:type depth: int, optional
.. py:class:: Sdg(qubits_idx='full', num_qubits=None, depth=1)
基类::py:class:`paddle_quantum.gate.base.Gate`
单量子比特S dagger(逆S)门。
其矩阵形式为:
.. math::
S ^\dagger =
\begin{bmatrix}
1 & 0\ \
0 & -i
\end{bmatrix}
:param qubits_idx:作用在的量子比特的编号,默认为``'full'``。
:type qubits_idx: Union[Iterable, int, str], optional
:param num_qubits:总的量子比特个数,默认为``None``。
:type num_qubits: int, optional
:param depth: 层数,默认为``1``。
:type depth: int, optional
.. py:class:: T(qubits_idx='full', num_qubits=None, depth=1)
基类::py:class:`paddle_quantum.gate.base.Gate`
......@@ -72,6 +95,29 @@ paddle\_quantum.gate.single\_qubit\_gate
:param depth: 层数,默认为 ``1``。
:type depth: int, optional
.. py:class:: Tdg(qubits_idx='full', num_qubits=None, depth=1)
基类::py:class:`paddle_quantum.gate.base.Gate`
单量子比特T dagger(逆T)门。
其矩阵形式为:
.. math::
T ^\dagger =
\begin{bmatrix}
1 & 0\ \
0 & e^{-\frac{i\pi}{4}}
\end{bmatrix}
:param qubits_idx:作用在的量子比特的编号,默认为``'full'``。
:type qubits_idx: Union[Iterable, int, str], optional
:param num_qubits:总的量子比特个数,默认为``None``。
:type num_qubits: int, optional
:param depth: 层数,默认为``1``。
:type depth: int, optional
.. py:class:: X(qubits_idx='full', num_qubits=None, depth=1)
基类::py:class:`paddle_quantum.gate.base.Gate`
......
......@@ -8,7 +8,7 @@ paddle\_quantum.linalg
计算矩阵范数
:param mat: 矩阵
:type mat: paddle.Tensor
:type mat: Union[np.ndarray, paddle.Tensor, State]
:return: 范数
:rtype: float
......@@ -18,17 +18,17 @@ paddle\_quantum.linalg
计算矩阵的转置共轭
:param mat: 矩阵
:type mat: paddle.Tensor
:type mat: Union[np.ndarray, paddle.Tensor]
:return: 矩阵的转置共轭
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: is_hermitian(mat, eps=1e-6)
验证矩阵 ``P`` 是否为厄密矩阵
:param mat: 厄密矩阵
:type mat: paddle.Tensor
:type mat: Union[np.ndarray, paddle.Tensor]
:param eps: 容错率
:type eps: float, optional
......@@ -40,7 +40,7 @@ paddle\_quantum.linalg
验证矩阵 ``P`` 是否为映射算子
:param mat: 映射算子
:type mat: paddle.Tensor
:type mat: Union[np.ndarray, paddle.Tensor]
:param eps: 容错率
:type eps: float, optional
......@@ -52,7 +52,7 @@ paddle\_quantum.linalg
验证矩阵 ``P`` 是否为酉矩阵
:param mat: 酉矩阵
:type mat: paddle.Tensor
:type mat: Union[np.ndarray, paddle.Tensor]
:param eps: 容错率
:type eps: float, optional
......@@ -116,11 +116,23 @@ paddle\_quantum.linalg
:param num_qubits: 量子比特数 n
:type num_qubits: int
:param is_unitary: 厄密矩阵块是否是酉矩阵的 1/2
:type is_unitary: bool
:type is_unitary: bool, optional
:return: 一个左上半部分为厄密矩阵的 :math:`2^n \times 2^n` 酉矩阵 (n 为量子比特数)
:rtype: paddle.Tensor
.. py:function:: block_enc_herm(mat, num_block_qubits)
生成厄密矩阵的分组编码
:param mat: 用于分组编码的矩阵
:type mat: Union[np.ndarray, paddle.Tensor]
:param num_block_qubits: 用于分组编码的辅助量子比特数
:type num_block_qubits: int, optional
:return: 返回分组编码后的酉矩阵
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: haar_orthogonal(num_qubits)
生成一个服从 Haar random 的正交矩阵。采样算法参考文献: arXiv:math-ph/0609050v2
......@@ -167,16 +179,54 @@ paddle\_quantum.linalg
:return: 一个 :math:`2^n \times 2^n` 密度矩阵 (n 为量子比特数)
:rtype: paddle.Tensor
.. py:function:: direct_sum(A,B)
计算A和B的直和
:param A: :math:`m \times n` 的矩阵
:type A: Union[np.ndarray, paddle.Tensor]
:param B: :math:`p \times q` 的矩阵
:type B: Union[np.ndarray, paddle.Tensor]
:return: A和B的直和,维度为 :math:`(m + p) \times (n + q)`
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: NKron(matrix_A, matrix_B, *args)
计算两个及以上的矩阵的克罗内克乘积
:param matrix_A: 矩阵
:type num_qubits: Union[np.ndarray, paddle.Tensor]
:type matrix_A: Union[np.ndarray, paddle.Tensor]
:param matrix_B: 矩阵
:type matrix_B: Union[np.ndarray, paddle.Tensor]
:param \*args: 更多矩阵
:type \*args: Union[np.ndarray, paddle.Tensor]
.. code-block:: python
from paddle_quantum.linalg import density_op_random, NKron
A = density_op_random(2)
B = density_op_random(2)
C = density_op_random(2)
result = NKron(A, B, C)
.. note::
上述代码块的 ``result`` 应为 :math:`A \otimes B \otimes C`
:return: 克罗内克乘积
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: herm_transform(fcn, mat, ignore_zero)
厄密矩阵的函数变换
:param fcn: 可以展开成泰勒级数的函数 `f`
:type fcn: Callable[[float], float]
:param mat: 厄密矩阵 :math:`H`
:type mat: Union[paddle.Tensor, np.ndarray, State]
:param ignore_zero: 是否忽略特征值0所在的特征空间,默认为 ``False``
:type ignore_zero: bool, optional
:return: :math:`f(H)`
:rtype: paddle.Tensor
\ No newline at end of file
......@@ -8,7 +8,7 @@ paddle\_quantum.qinfo
计算量子态的偏迹。
:param state: 输入的量子态。
:type state: Union[paddle_quantum.State, paddle.Tensor]
:type state: Union[np.ndarray, paddle.Tensor, State]
:param dim1: 系统A的维数。
:type dim1: int
:param dim2: 系统B的维数。
......@@ -17,19 +17,19 @@ paddle\_quantum.qinfo
:type A_or_B: int
:return: 输入的量子态的偏迹。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor, State]
.. py:function:: partial_trace_discontiguous(state, preserve_qubits=None)
计算量子态的偏迹,可选取任意子系统。
:param state: 输入的量子态。
:type state: Union[paddle_quantum.State, paddle.Tensor]
:type state: Union[np.ndarray, paddle.Tensor, State]
:param preserve_qubits: 要保留的量子比特,默认为 None,表示全保留。
:type preserve_qubits: list, optional
:return: 所选子系统的量子态偏迹。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor, State]
.. py:function:: trace_distance(rho, sigma)
......@@ -40,12 +40,12 @@ paddle\_quantum.qinfo
D(\rho, \sigma) = 1 / 2 * \text{tr}|\rho-\sigma|
:param rho: 量子态的密度矩阵形式。
:type rho: Union[paddle_quantum.State, paddle.Tensor]
:type rho: Union[np.ndarray, paddle.Tensor, State]
:param sigma: 量子态的密度矩阵形式。
:type sigma: Union[paddle_quantum.State, paddle.Tensor]
:type sigma: Union[np.ndarray, paddle.Tensor, State]
:return: 输入的量子态之间的迹距离。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: state_fidelity(rho, sigma)
......@@ -56,11 +56,11 @@ paddle\_quantum.qinfo
F(\rho, \sigma) = \text{tr}(\sqrt{\sqrt{\rho}\sigma\sqrt{\rho}})
:param rho: 量子态的密度矩阵形式。
:type rho: Union[paddle_quantum.State, paddle.Tensor]
:type rho: Union[np.ndarray, paddle.Tensor, State]
:param sigma: 量子态的密度矩阵形式。
:type sigma: Union[paddle_quantum.State, paddle.Tensor]
:type sigma: Union[np.ndarray, paddle.Tensor, State]
:return: 输入的量子态之间的保真度。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: gate_fidelity(U, V)
......@@ -73,12 +73,12 @@ paddle\_quantum.qinfo
:math:`U` 是一个 :math:`2^n\times 2^n` 的 Unitary 矩阵。
:param U: 量子门 :math:`U` 的酉矩阵形式
:type U: paddle.Tensor
:type U: Union[np.ndarray, paddle.Tensor]
:param V: 量子门 :math:`V` 的酉矩阵形式
:type V: paddle.Tensor
:type V: Union[np.ndarray, paddle.Tensor]
:return: 输入的量子门之间的保真度
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: purity(rho)
......@@ -89,12 +89,12 @@ paddle\_quantum.qinfo
P = \text{tr}(\rho^2)
:param rho: 量子态的密度矩阵形式。
:type rho: Union[paddle_quantum.State, paddle.Tensor]
:type rho: Union[np.ndarray, paddle.Tensor, State]
:return: 输入的量子态的纯度。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: von_neumann_entropy(rho)
.. py:function:: von_neumann_entropy(rho, base)
计算量子态的冯诺依曼熵。
......@@ -103,12 +103,14 @@ paddle\_quantum.qinfo
S = -\text{tr}(\rho \log(\rho))
:param rho: 量子态的密度矩阵形式。
:type rho: Union[paddle_quantum.State, paddle.Tensor]
:type rho: Union[np.ndarray, paddle.Tensor, State]
:param base: 对数的底。默认为2。
:type base: int, optional
:return: 输入的量子态的冯诺依曼熵。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: relative_entropy(rho, sig)
.. py:function:: relative_entropy(rho, sig, base)
计算两个量子态的相对熵。
......@@ -117,12 +119,14 @@ paddle\_quantum.qinfo
S(\rho \| \sigma)=\text{tr} \rho(\log \rho-\log \sigma)
:param rho: 量子态的密度矩阵形式
:type rho: Union[paddle_quantum.State, paddle.Tensor]
:type rho: Union[np.ndarray, paddle.Tensor, State]
:param sig: 量子态的密度矩阵形式
:type sig: Union[paddle_quantum.State, paddle.Tensor]
:type sig: Union[np.ndarray, paddle.Tensor, State]
:param base: 对数的底。默认为2.
:type base: int, optional
:return: 输入的量子态之间的相对熵
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: random_pauli_str_generator(n, terms=3)
......@@ -163,51 +167,51 @@ paddle\_quantum.qinfo
计算输入量子态的 partial transpose :math:`\rho^{T_A}`。
:param density_op: 量子态的密度矩阵形式。
:type density_op: Union[paddle_quantum.State, paddle.Tensor]
:type density_op: Union[np.ndarray, paddle.Tensor, State]
:param sub_system: 1或2,表示关于哪个子系统进行 partial transpose,默认为第二个。
:type sub_system: int, optional
:return: 输入的量子态的 partial transpose
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: partial_transpose(density_op, n)
计算输入量子态的 partial transpose :math:`\rho^{T_A}`。
:param density_op: 量子态的密度矩阵形式。
:type density_op: Union[paddle_quantum.State, paddle.Tensor]
:type density_op: Union[np.ndarray, paddle.Tensor, State]
:param n: 需要转置系统的量子比特数量。
:type n: int
:return: 输入的量子态的 partial transpose。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: negativity(density_op)
计算输入量子态的 Negativity :math:`N = ||\frac{\rho^{T_A}-1}{2}||`。
:param density_op: 量子态的密度矩阵形式。
:type density_op: Union[paddle_quantum.State, paddle.Tensor]
:type density_op: Union[np.ndarray, paddle.Tensor, State]
:return: 输入的量子态的 Negativity。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: logarithmic_negativity(density_op)
计算输入量子态的 Logarithmic Negativity :math:`E_N = ||\rho^{T_A}||`。
:param density_op: 量子态的密度矩阵形式。
:type density_op: Union[paddle_quantum.State, paddle.Tensor]
:type density_op: Union[np.ndarray, paddle.Tensor, State]
:return: 输入的量子态的 Logarithmic Negativity。
:rtype: paddle.Tensor
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: is_ppt(density_op)
计算输入量子态是否满足 PPT 条件。
:param density_op: 量子态的密度矩阵形式。
:type density_op: Union[paddle_quantum.State, paddle.Tensor]
:type density_op: Union[np.ndarray, paddle.Tensor, State]
:return: 输入的量子态是否满足 PPT 条件。
:rtype: bool
......@@ -217,7 +221,7 @@ paddle\_quantum.qinfo
计算输入量子态的施密特分解 :math:`\lvert\psi\rangle=\sum_ic_i\lvert i_A\rangle\otimes\lvert i_B \rangle`。
:param psi: 量子态的向量形式,形状为(2**n)。
:type psi: Union[paddle_quantum.State, paddle.Tensor]
:type psi: Union[np.ndarray, paddle.Tensor, State]
:param sys_A: 包含在子系统 A 中的 qubit 下标(其余 qubit 包含在子系统B中),默认为量子态 :math:`\lvert \psi\rangle` 的前半数 qubit。
:type sys_A: List[int], optional
......@@ -228,7 +232,7 @@ paddle\_quantum.qinfo
- 由子系统A的基 :math:`\lvert i_A\rangle` 组成的高维数组,形状为 ``(k, 2**m, 1)``。
- 由子系统B的基 :math:`\lvert i_B\rangle` 组成的高维数组,形状为 ``(k, 2**l, 1)``。
:rtype: Tuple[paddle.Tensor]
:rtype: Union[Tuple[paddle.Tensor, paddle.Tensor, paddle.Tensor], Tuple[np.ndarray, np.ndarray, np.ndarray]]
.. py:function:: image_to_density_matrix(image_filepath)
......@@ -258,22 +262,74 @@ paddle\_quantum.qinfo
:return: 估计可观测量 :math:`H` 的期望值。
:rtype: float
.. py:function:: tensor_product(state_a, state_b, *args)
.. py:function:: tensor_state(state_a, state_b, *args)
计算输入的量子态(至少两个)的直积形式, 输出将自动返回 State 实例
:param state_a: 量子态A
:type state_a: Union[State, paddle.Tensor]
:type state_a: State
:param state_b: 量子态B
:type state_b: Union[State, paddle.Tensor]
:type state_b: State
:param args: 其他量子态
:type args: Union[State, paddle.Tensor]
:raises NotImplementedError: 当前只接收输入类型为 State 或 paddle.Tensor
:type args: State
.. note::
使用的 backend 必须为 DensityMatrix
需要注意输入态使用的 backend;
若输入数据为 ``paddle.Tensor`` 或者 ``numpy.ndarray``,请使用 ``paddle_quantum.linalg.NKron`` 函数处理。
:return: 输入量子态的直积
:rtype: State
\ No newline at end of file
:rtype: State
.. py:function:: diamond_norm(channel_repr, dim_io, **kwargs)
计算输入的菱形范数
:param channel_repr: 信道对应的表示, ``ChoiRepr`` 或 ``KrausRepr`` 或 ``StinespringRepr`` 或 ``paddle.Tensor``。
:type channel_repr: Union[ChoiRepr, KrausRepr, StinespringRepr, paddle.Tensor]
:param dim_io: 输入和输出的维度。
:type dim_io: Union[int, Tuple[int, int]], optional.
:param kwargs: 使用cvx所需的参数。
:type kwargs: Any
:raises RuntimeError: ``channel_repr`` 必须是 ``ChoiRepr`` 或 ``KrausRepr`` 或 ``StinespringRepr`` 或 ``paddle.Tensor``。
:raises TypeError: "dim_io" 必须是 "int" 或者 "tuple"。
:warning: 输入的 ``channel_repr`` 不是choi表示, 已被转换成 ``ChoiRepr``。
:return: 返回菱形范数
:rtype: float
.. py:function:: channel_convert(original_channel, target, tol)
将给定的信道转换成目标形式
:param original_channel: 输入信道
:type original_channel: Union[ChoiRepr, KrausRepr, StinespringRepr]
:param target: 目标形式,应为 ``Choi``, ``Kraus`` 或 ``Stinespring``
:type target: str
:param tol: 容错误差
:type tol: float, optional
:raises ValueError: 不支持的信道表示形式,应为 ``Choi``, ``Kraus`` 或 ``Stinespring``.
.. note::
choi变为kraus目前因为eigh的精度会存在1e-6的误差
:raises NotImplementedError: 不支持输入数据类型的信道转换
:return: 返回目标形式的信道
:rtype: Union[ChoiRepr, KrausRepr, StinespringRepr]
.. py:function:: kraus_oper_random(num_qubits: int, num_oper: int)
随机输出一组描述量子信道的Kraus算符
:param num_qubits: 信道对应的量子比特数量
:type num_qubits: int
:param num_oper: Kraus算符的数量
:type num_oper: int
:return: 一组Kraus算符
:rtype: list
\ No newline at end of file
paddle\_quantum.qml
=============================
量子机器学习模块。
.. rubric:: Submodules
.. toctree::
:maxdepth: 4
paddle_quantum.qml.vsql
paddle\_quantum.qml.vsql
==============================================
VSQL 模型。
.. py:function:: norm_image(images, num_qubits)
对输入的图片进行归一化。先将图片展开为向量,再进行归一化。
:param images: 输入的图片。
:type images: List[np.ndarray]
:param num_qubits: 量子比特的数量,决定了归一化向量的维度。
:type num_qubits: int
:return: 返回归一化之后的向量,它是由 ``paddle.Tensor`` 组成的列表。
:rtype: List[paddle.Tensor]
.. py:function:: data_loading(num_qubits, mode, classes, num_data)
加载 MNIST 数据集,其中只包含指定的数据。
:param num_qubits: 量子比特的数量,决定了归一化向量的维度。
:type num_qubits: int
:param mode: 指定要加载的数据集,为 ``'train'`` 或 ``'test'`` 。
- ``'train'`` :表示加载训练集。
- ``'test'`` :表示加载测试集。
:type mode: str
:param classes: 要加载的数据的标签。对应标签的数据会被加载。
:type classes: list
:param num_data: 要加载的数据的数量。默认为 ``None`` ,加载所有数据。
:type num_data: Optional[int]
:return: 返回加载的数据集,其组成为 ``(images, labels)`` 。
:rtype: Tuple[List[np.ndarray], List[int]]
.. py:function:: observable(start_idx, num_shadow)
生成测量量子态所需要的哈密顿量。
:param start_idx: 要测量的量子比特的起始索引。
:type start_idx: int
:param num_shadow: 影子电路所包含的量子比特的数量。
:type num_shadow: int
:return: 返回生成的哈密顿量。
:rtype: paddle_quantum.Hamiltonian
.. py:class:: VSQL(num_qubits, num_shadow, num_classes, depth)
基类::py:class:`paddle.nn.Layer`
变分影子量子学习(variational shadow quantum learning, VSQL)模型的实现。具体细节可以参考:https://ojs.aaai.org/index.php/AAAI/article/view/17016 。
:param num_qubits: 量子电路所包含的量子比特的数量。
:type num_qubits: int
:param num_shadow: 影子电路所包含的量子比特的数量。
:type num_shadow: int
:param num_classes: 模型所要分类的类别的数量。
:type num_classes: int
:param depth: 量子电路的深度,默认为 ``1`` 。
:type depth: Optional[int]
.. py:method:: forward(batch_input)
:param batch_input: 模型的输入,其形状为 :math:`(\text{batch_size}, 2^{\text{num_qubits}})` 。
:type batch_input: List[paddle.Tensor]
:return: 返回模型的输出,其形状为 :math:`(\text{batch_size}, \text{num_classes})` 。
:rtype: paddle.Tensor
.. py:function:: train(num_qubits, num_shadow, depth, batch_size, epoch, learning_rate, classes, num_train, num_test)
训练 VSQL 模型。
:param num_qubits: 量子电路所包含的量子比特的数量。
:type num_qubits: int
:param num_shadow: 影子电路所包含的量子比特的数量。
:type num_shadow: int
:param depth: 量子电路的深度,默认为 ``1`` 。
:type depth: Optional[int]
:param batch_size: 数据的批大小,默认为 ``16`` 。
:type batch_size: Optional[int]
:param epoch: 训练的轮数,默认为 ``10`` 。
:type epoch: Optional[int]
:param learning_rate: 更新参数的学习率,默认为 ``0.01`` 。
:type learning_rate: Optional[float]
:param classes: 要预测的手写数字的类别。默认为 ``None`` ,即预测所有的类别。
:type classes: Optional[list]
:param num_train: 训练集的数据量。默认为 ``None`` ,即使用所有的训练数据。
:type num_train: Optional[int]
:param num_test: 测试集的数据量。默认为 ``None`` ,即使用所有的训练数据。
:type num_test: Optional[int]
paddle\_quantum.qpp.angles
===============================
量子相位处理相关工具函数包
.. py:function:: qpp_angle_finder(P, Q)
对一个劳伦对 ``P``, ``Q``,找到相应的角度集合
:param P: 一个劳伦多项式
:type P: Laurent
:param Q: 一个劳伦多项式
:type Q: Laurent
:return:
包含如下元素:
-list_theta: :math:`R_Y` 门对应的角度
-list_phi: :math:`R_Z` 门对应的角度
:rtype: Tuple[List[float], List[float]]
.. py:function:: qpp_angle_approximator(P, Q)
对一个劳伦对 ``P``, ``Q``,估计相应的角度集合
:param P: 一个劳伦多项式
:type P: Laurent
:param Q: 一个劳伦多项式
:type Q: Laurent
:return:
包含如下元素:
-list_theta: :math:`R_Y` 门对应的角度
-list_phi: :math:`R_Z` 门对应的角度
:rtype: Tuple[List[float], List[float]]
.. note::
与 `yzzyz_angle_finder` 不同的是, `yzzyz_angle_approximator` 假定唯一的误差来源是精度误差(而这一般来讲是不正确的)。
.. py:function:: update_angle(coef)
通过 `coef` 从 ``P`` 和 ``Q`` 中计算角度
:param coef: ``P`` 和 ``Q`` 中的第一项和最后一项
:type coef: List[complex]
:return: 角度 `theta` 和 `phi`
:rtype: Tuple[float, float]
:raises ValueError: 参数错误:检查这四个参数{[p_d, p_nd, q_d, q_nd]}
.. py:function:: update_polynomial(P, Q, theta, phi, verify)
通过 `theta` , `phi` 更新 ``P`` , ``Q``
:param P: 一个劳伦多项式
:type P: Laurent
:param Q: 一个劳伦多项式
:type Q: Laurent
:param theta: 一个参数
:type theta: float
:param phi: 一个参数
:type phi: float
:param verify: 验证计算是否正确,默认值为True
:type verify: Optional[bool] = True
:return: 更新后的 ``P``, ``Q``
:rtype: Tuple[List[float], List[float]]
.. py:function:: condition_test(P, Q)
检查 ``P``, ``Q`` 是否满足:
- deg(`P`) = deg(`Q`)
- ``P``, ``Q`` 是否具有相同宇称
- :math:`PP^* + QQ^* = 1`
:param P: 一个劳伦多项式
:type P: Laurent
:param Q: 一个劳伦多项式
:type Q: Laurent
:raises ValueError: PP* + QQ* != 1: 检查你的代码
.. py:function:: yz_decomposition(U)
返回U的yz分解
:param U: 单比特幺正变换
:type U: np.ndarray
:return: `alpha`, `theta`, `phi` 使得 :math:`U[0, 0] = \alpha R_Y(\theta) R_Z(\phi) [0, 0]`
:rtype: Tuple[complex, float, float]
\ No newline at end of file
paddle\_quantum.qpp.laurent
===============================
劳伦类的定义和它的函数
.. py:class:: Laurent
基类: :py:class:`object`
为劳伦多项式定义的类,定义为 :math:`P:\mathbb{C}[X, X^{-1}] \to \mathbb{C} :x \mapsto \sum_{j = -L}^{L} p_j X^j`
:param coef: 劳伦多项式系数的列表,排列为 :math:`\{p_{-L}, ..., p_{-1}, p_0, p_1, ..., p_L\}`
:type coef: np.ndarray
.. py:method:: __call__(X)
计算P(X)的值
:param X: 输入X
:type X: Union[int, float, complex]
:return: P(X)
:rtype: complex
.. py:property:: coef()
以上升顺序给出多项式的系数序列
.. py:property:: conj()
给出多项式的共轭
.. py:property:: roots()
给出多项式根的列表
.. py:property:: norm()
给出多项式系数的绝对值平方之和
.. py:property:: max_norm()
给出多项式的系数的绝对值的最大值
.. py:property:: parity()
给出多项式的宇称
.. py:method:: __copy__()
复制劳伦多项式
:return: 复制后的多项式
:rtype: Laurent
.. py:method:: __add__(other)
劳伦多项式的相加
:param other: 一个标量或一个劳伦多项式 :math:`Q(x) = \sum_{j = -L}^{L} q_{j} X^j`
:type other: Any
:raises TypeError: 不支持劳伦多项式和others的相加
.. py:method:: __mul__(other)
劳伦多项式的相乘
:param other: 一个标量或一个劳伦多项式 :math:`Q(x) = \sum_{j = -L}^{L} q_{j} X^j`
:type other: Any
:raises TypeError: 不支持劳伦多项式和others的相乘
.. py:method:: __sub__(other)
劳伦多项式的相减
:param other: 一个标量或一个劳伦多项式 :math:`Q(x) = \sum_{j = -L}^{L} q_{j} X^j`
:type other: Any
.. py:method:: __eq__(other)
劳伦多项式的相等
:param other: 一个标量或一个劳伦多项式 :math:`Q(x) = \sum_{j = -L}^{L} q_{j} X^j`
:type other: Any
:raises TypeError: 不支持劳伦多项式和 ``others`` 的相等
.. py:method:: __str__()
打印劳伦多项式
.. py:method:: is_parity(p)
检验劳伦多项式是否有确定宇称
:param p: 宇称
:type p: int
:return:
包含以下元素:
-宇称是否是 ``p mod 2``
-如果不是,返回破坏该宇称的绝对值最大的系数
-如果不是,返回破坏该宇称的绝对值最小的系数
:rtype: Tuple[bool, complex]
.. py:function:: revise_tol(t)
回顾 ``TOL`` 的值
:param t: TOL的值
:type t: float
.. py:function:: ascending_coef(coef)
通过 ``coef`` 从 ``P`` 和 ``Q`` 中计算角度
:param coef: 排列成 :math:`\{ p_0, ..., p_L, p_{-L}, ..., p_{-1} \}` 的系数列表
:type coef: np.ndarray
:return: 排列成 :math:`\{ p_{-L}, ..., p_{-1}, p_0, p_1, ..., p_L \}` 的系数列表
:rtype: np.ndarray
.. py:function:: remove_abs_error(data, tol)
移除数据中的错误
:param data: 数据数组
:type data: np.ndarray
:param tol: 容错率
:type tol: Optional[float] = None
:return: 除错后的数据
:rtype: np.ndarray
.. py:function:: random_laurent_poly(deg, parity, is_real)
随机生成一个劳伦多项式
:param deg: 该多项式的度数
:type deg: int
:param parity: 该多项式的宇称,默认为 ``none``
:type parity: Optional[int] = None
:param is_real: 该多项式系数是否是实数,默认为 ``false``
:type is_real: Optional[bool] = False
:return: 一个模小于等于1的劳伦多项式
:rtype: Laurent
.. py:function:: sqrt_generation(A)
生成劳伦多项式 :math:`A` 的平方根
:param A: 一个劳伦多项式
:type A: Laurent
:return: 一个模小于等于1的劳伦多项式
:rtype: Laurent
.. py:function:: Q_generation(P)
生成劳伦多项式 :math:`P` 的互补多项式
:param P: 一个宇称为 :math:`deg` ,度数为 :math:`L` 的劳伦多项式
:type P: Laurent
:return: 一个宇称为 :math:`deg` ,度数为 :math:`L` 的劳伦多项式 :math:`Q` ,使得 :math:`PP^* + QQ^* = 1`
:rtype: Laurent
.. py:function:: pair_generation(f)
生成劳伦多项式 :math:`f` 的劳伦对
:param f: 一个实的,偶次的,max_norm小于1的劳伦多项式
:type f: Laurent
:return: 劳伦多项式 :math:`P, Q` 使得 :math:`P = \sqrt{1 + f / 2}, Q = \sqrt{1 - f / 2}`
:rtype: Laurent
.. py:function:: laurent_generator(fn, dx, deg, L)
生成劳伦多项式 :math:`f` 的劳伦对
:param fn: 要近似的函数
:type fn: Callable[[np.ndarray], np.ndarray]
:param dx: 数据点的采样频率
:type dx: float
:param deg: 劳伦多项式的度数
:type deg: int
:param L: 近似宽度的一半
:type L: float
:return: 一个度数为 ``deg`` 的,在区间 :math:`[-L, L]` 内近似`fn` 的劳伦多项式
:rtype: Laurent
.. py:function:: deg_finder(fn, delta, l)
找到一个度数,使得由 ``laurent_generator`` 生成的劳伦多项式具有小于1的max_norm
:param fn: 要近似的函数
:type fn: Callable[[np.ndarray], np.ndarray]
:param delta: 数据点的采样频率,默认值为 :math:`0.00001 \pi`
:type delta: Optional[float] = 0.00001 * np.pi
:param l: 近似宽度的一半,默认值为 :math:`\pi`
:type l: Optional[float] = np.pi
:return: 该近似的度数
:rtype: int
.. py:function:: step_laurent(deg)
生成一个近似阶梯函数的劳伦多项式
:param deg: 输出劳伦多项式的度数(为偶数)
:type deg: int
:return: 一个估计 :math:`f(x) = 0.5` if :math:`x <= 0` else :math:`0` 的劳伦多项式
:rtype: Laurent
.. note::
在哈密顿量能量计算器中使用
.. py:function:: hamiltonian_laurent(t, deg)
生成一个近似哈密顿量演化函数的劳伦多项式
:param t: 演化常数(时间)
:type t: float
:param deg: 输出劳伦多项式的度数(为偶数)
:type deg: int
:return: 一个估计 :math:`e^{it \cos(x)}` 的劳伦多项式
:rtype: Laurent
.. note::
-起源于Jacobi-Anger展开: :math:`y(x) = \sum_n i^n Bessel(n, x) e^{inx}`
-在哈密顿量模拟中使用
.. py:function:: ln_laurent(deg, t)
生成一个近似ln函数的劳伦多项式
:param deg: 劳伦多项式的度数(是4的因子)
:type deg: int
:param t: 归一化常数
:type t: float
:return: 一个估计 :math:`ln(cos(x)^2) / t` 的劳伦多项式
:rtype: Laurent
.. note::
在冯诺依曼熵的估计中使用。
.. py:function:: comb(n, k)
计算nCr(n, k)
:param n: 输入参数
:type n: float
:param k: 输入参数
:type k: int
:return: nCr(n, k)
:rtype: float
.. py:function:: power_laurent(deg, alpha, t)
生成近似幂函数的劳伦多项式
:param deg: 劳伦多项式的度数(是4的因子)
:type deg: int
:param alpha: 幂函数的幂次
:type alpha: int
:param t: 归一化常数
:type t: float
:return: 一个估计 :math:`(cos(x)^2)^{\alpha / 2} / t` 的劳伦多项式
:rtype: Laurent
paddle\_quantum.qpp
============================
量子相位处理模块
.. rubric:: Submodules
.. toctree::
:maxdepth: 4
paddle_quantum.qpp.angles
paddle_quantum.qpp.laurent
paddle_quantum.qpp.utils
\ No newline at end of file
paddle\_quantum.qpp.utils
============================
QPP 线路变换和其他相关工具。更多细节参考论文 https://arxiv.org/abs/2209.14278 中的 Theorem 6。
.. py:function:: qpp_cir(list_theta, list_phi, U) -> Circuit
根据 ``list_theta`` 和 ``list_phi`` 创建量子相位处理器
:param list_theta: :math:`R_Y` 门角度输入。
:type list_theta: Union[np.ndarray, paddle.Tensor]
:param list_phi: :math:`R_Z` 门角度输入。
:type list_phi: Union[np.ndarray, paddle.Tensor]
:param U: 酉矩阵或标量输入。
:type U: Union[np.ndarray, paddle.Tensor, float]
:return: 三角 QSP 的多比特一般化线路。
:rtype: Circuit
.. py:function:: simulation_cir(fn, U, approx=True, deg=50, length=np.pi, step_size=0.00001*np.pi, tol=1e-30)
返回一个模拟 ``fn`` 的 QPP 线路,见论文 https://arxiv.org/abs/2209.14278 中的 Theorem 6。
:param fn: 要模拟的函数。
:type fn: Callable[[np.ndarray], np.ndarray]
:param U: 酉矩阵。
:type U: Union[np.ndarray, paddle.Tensor, float]
:param approx: 是否估算线路角度。默认为 ``True``。
:type approx: : Optional[bool]
:param deg: 模拟的级数。默认为 ``50``。
:type deg: : Optional[int]
:param length: 模拟宽度的一半。默认为 :math:`\pi`。
:type length: Optional[float]
:param step_size: 采样点的频率。默认为 :math:`0.00001 \pi`。
:type step_size: Optional[float]
:param tol: 误差容忍度。默认为 :math:`10^{-30}`,即机械误差。
:type tol: Optional[float]
:return: 模拟 ``fn`` 的 QPP 线路。
:rtype: Circuit
.. py:function:: qps(U, initial_state)
量子相位搜索算法,见论文 https://arxiv.org/abs/2209.14278 中的算法 1 和 2
:param U: 目标酉矩阵。
:type U: Union[np.ndarray, paddle.Tensor]
:param initial_state: 输入量子态。
:type initial_state: Union[np.ndarray, paddle.Tensor, State]
:return: 包含如下元素的 tuple:
- 一个 ``U`` 的本征相位;
- 其相位对应的,存在和 ``initial_state`` 内积不为零的本征态。
:rtype: Tuple[float, State]
.. py:function:: qubitize(block_enc, num_block_qubits)
使用一个额外辅助比特来比特化块编码,来保证子空间不变。更多细节见论文 http://arxiv.org/abs/1610.06546。
:param block_enc: 目标块编码。
:type block_enc: Union[np.ndarray, paddle.Tensor]
:param num_block_qubits: 块编码自身所使用的辅助比特数。
:type num_block_qubits: int
:return: 比特化的 ``block_enc``
:rtype: paddle.Tensor
.. py:function:: purification_block_enc(num_qubits, num_block_qubits):
随机生成一个 :math:`n`-比特密度矩阵的 :math:`(n + m)`-比特的比特化块编码。
:param num_qubits: 量子态比特数 :math:`n`。
:type num_qubits: int
:param num_block_qubits: 块编码的辅助比特数 :math:`m > n`。
:type num_block_qubits: int
:return: 一个 :math:`2^{n + m} \times 2^{n + m}` 的左上角为密度矩阵的酉矩阵
:rtype: paddle.Tensor
......@@ -10,7 +10,7 @@ paddle\_quantum.qsvt.qsp\_utils
:param degree: 多项式的度
:type degree: int
:param odd: 多项式的奇偶性,输入 `True` 则为奇函数, `False` 则为偶函数
:type odd: bool
:type od: bool
:return: 一个随机生成的多项式
:rtype: Polynomial
......
......@@ -17,8 +17,7 @@ paddle\_quantum.state.state
:type backend: paddle_quantum.Backend, optional
:param dtype: 量子态的数据类型。默认为 None,使用全局的默认数据类型。
:type dtype: str, optional
:raises Exception: 所输入的量子态维度不正确。
:raises NotImplementedError: 所指定的后端必须为量桨已经实现的后端。
:raises ValueError: 无法识别后端
.. py:property:: ket()
......@@ -29,6 +28,56 @@ paddle\_quantum.state.state
得到量子态的行向量形式。
.. py:method:: normalize()
得到归一化后量子态
:raises NotImplementedError: 当前后端不支持归一化
.. py:method:: evolve(H,t)
得到经过给定哈密顿量演化后的量子态
:param H: 系统哈密顿量
:type H: Union[np.ndarray, paddle.Tensor, Hamiltonian]
:param t: 演化时间
:type t: float
:raises NotImplementedError: 当前后端不支持量子态演化
.. py:method:: kron(other)
得到与给定量子态之间的张量积
:param other: 给定量子态
:type other: State
:return: 返回张量积
:rtype: State
.. py:method:: __matmul__(other)
得到与量子态或张量之间的乘积
:param other: 给定量子态
:type other: State
:raises NotImplementedError: 不支持与该量子态进行乘积计算
:raises ValueError: 无法对两个态向量相乘,请检查使用的后端
:return: 返回量子态的乘积
:rtype: paddle.Tensor
.. py:method:: __rmatmul__(other)
得到与量子态或张量之间的乘积
:param other: 给定量子态
:type other: State
:raises NotImplementedError: 不支持与该量子态进行乘积计算
:raises ValueError: 无法对两个态向量相乘,请检查使用的后端
:return: 返回量子态的乘积
:rtype: paddle.Tensor
.. py:method:: numpy()
得到量子态的数据的 numpy 形式。
......@@ -48,8 +97,8 @@ paddle\_quantum.state.state
:type device: str
:param blocking: 如果为 False 并且当前 Tensor 处于固定内存上,将会发生主机到设备端的异步拷贝。否则会发生同步拷贝。如果为 None,blocking 会被设置为 True,默认 为False。
:type blocking: str
:return: 返回 NotImplementedError,该函数会在后续实现。
:rtype: Error
:raises NotImplementedError: 仅支持在态向量与密度矩阵之间进行转换
:raises NotImplementedError: 不支持在该设备或blocking上进行转换
.. py:method:: clone()
......@@ -86,3 +135,79 @@ paddle\_quantum.state.state
:raises NotImplementedError: 输入的量子比特下标有误。
:return: 测量结果。
:rtype: dict
.. py:function:: _type_fetch(data)
获取数据的类型
:param data: 输入数据
:type data: Union[np.ndarray, paddle.Tensor, State]
:raises ValueError: 输入量子态不支持所选后端
:raises TypeError: 无法识别输入量子态的数据类型
:return: 返回输入量子态的数据类型
:rtype: str
.. py:function:: _density_to_vector(rho)
将密度矩阵转换为态向量
:param rho: 输入的密度矩阵
:type rho: Union[np.ndarray, paddle.Tensor]
:raises ValueError: 输出量子态可能不为纯态
:return: 返回态向量
:rtype: Union[np.ndarray, paddle.Tensor]
.. py:function:: _type_transform(data, output_type)
将输入量子态转换成目标类型
:param data: 需要转换的数据
:type data: Union[np.ndarray, paddle.Tensor, State]
:param output_type: 目标数据类型
:type output_type: str
:raises ValueError: 输入态不支持转换为目标数据类型
:return: 返回目标数据类型的量子态
:rtype: Union[np.ndarray, paddle.Tensor, State]
.. py:function:: is_state_vector(vec, eps)
检查输入态是否为量子态向量
:param vec: 输入的数据 :math:`x`
:type vec: Union[np.ndarray, paddle.Tensor]
:param eps: 容错率
:type eps: float, optional
:return: 返回是否满足 :math:`x^\dagger x = 1` ,以及量子比特数目或错误信息
:rtype: Tuple[bool, int]
.. note::
错误信息为:
* ``-1`` 如果上述公式不成立
* ``-2`` 如果输入数据维度不为2的幂
* ``-3`` 如果输入数据不为向量
.. py:function:: is_density_matrix(rho, eps)
检查输入数据是否为量子态的密度矩阵
:param rho: 输入的数据 ``rho``
:type rho: Union[np.ndarray, paddle.Tensor]
:param eps: 容错率
:type eps: float, optional
:return: 返回输入数据 ``rho`` 是否为迹为1的PSD矩阵,以及量子比特数目或错误信息
:rtype: Tuple[bool, int]
.. note::
错误信息为:
* ``-1`` 如果 ``rho`` 不为PSD矩阵
* ``-2`` 如果 ``rho`` 的迹不为1
* ``-3`` 如果 ``rho`` 的维度不为2的幂
* ``-4`` 如果 ``rho`` 不为一个方阵
......@@ -28,7 +28,13 @@
"source": [
"## 量桨连接量易伏\n",
"\n",
"目前量桨已经支持连接量易伏,只需要使用 `paddle_quantum.set_backend('quleaf')` 即可将量桨的后端设置为量易伏。除此之外,我们还需要设置量易伏的模拟方式。如果使用云端算力,则还需要输入 token。因此,完整的设置代码如下:"
"### 环境设置\n",
"\n",
"如果要使用量桨连接量易伏上的真实量子计算机,则需要保证所安装的 qcompute 的版本在 3.0.0 以上,使用 `pip install -U qcompute` 来安装最新版本的 qcompute。\n",
"\n",
"其中,qcompute 对 protobuf 的版本要求是 4.21.1,而飞桨对 protobuf 的版本要求为 3.1.0 到3.20.0。因此,需要通过设置环境变量来使飞桨可以兼容更高版本的 protobuf。\n",
"\n",
"> 因为飞桨对 protobuf 的版本要求为 3.1.0 到3.20.0,所以所有的 Python 程序都需要先设置环境变量才能正常使用量桨。因此,如果不使用量易伏的话,可以通过 `pip install protobuf==3.20.0` 来正常使用量桨而无需额外设置环境变量。"
]
},
{
......@@ -36,6 +42,24 @@
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# 设置环境变量使飞桨可以兼容更高版本的 protobuf\n",
"import os\n",
"os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"接下来,只需要使用 `paddle_quantum.set_backend('quleaf')` 即可将量桨的后端设置为量易伏。除此之外,我们还需要设置量易伏的模拟方式。如果使用云端算力,则还需要输入 token。因此,完整的设置代码如下:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import paddle_quantum\n",
"from QCompute import BackendName\n",
......@@ -79,7 +103,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
......@@ -109,21 +133,21 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The iter is 0, loss is -0.32104.\n",
"The iter is 10, loss is -0.49239.\n",
"The iter is 20, loss is -0.80956.\n",
"The iter is 30, loss is -1.07812.\n",
"The iter is 40, loss is -1.09850.\n",
"The iter is 50, loss is -1.13334.\n",
"The iter is 60, loss is -1.13445.\n",
"The iter is 70, loss is -1.13492.\n",
"The iter is 0, loss is -0.36935.\n",
"The iter is 10, loss is -0.51383.\n",
"The iter is 20, loss is -0.74604.\n",
"The iter is 30, loss is -1.02815.\n",
"The iter is 40, loss is -1.07233.\n",
"The iter is 50, loss is -1.09937.\n",
"The iter is 60, loss is -1.11564.\n",
"The iter is 70, loss is -1.11459.\n",
"The theoretical value is -1.137283834485513.\n"
]
}
......@@ -167,7 +191,7 @@
"loss_func = paddle_quantum.loss.ExpecVal(hamiltonian, shots=10000)\n",
"# 进行迭代训练\n",
"num_itr = 80\n",
"for itr in range(0, num_itr):\n",
"for itr in range(num_itr):\n",
" state = circuit(init_state)\n",
" loss = loss_func(state)\n",
" loss.backward()\n",
......@@ -190,7 +214,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.8.0 ('paddle-quantum-dev')",
"display_name": "Python 3.8.0 ('temp')",
"language": "python",
"name": "python3"
},
......@@ -209,7 +233,7 @@
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "9043b12ec77a531919bc05f05830335d23baf822720cbea14b03018197d26545"
"hash": "73730e2524c172926674de584a45f4a289689f765fd1f4813f545a2476542e53"
}
}
},
......
......@@ -28,7 +28,13 @@
"source": [
"## Paddle Quantum calls QuLeaf\n",
"\n",
"In the paddle quantum, we already support the backend implementation of QuLeaf. Just use `paddle_quantum.set_backend('quleaf')` to set the backend of the quantum paddle to QuLeaf. In addition to that, we need to set the simulation method of the QuLeaf. If we use cloud computation power, we also need to enter the token, so the complete setup code is as follows."
"### Environment settings\n",
"\n",
"If you want to use paddle-quantum to connect to the real quantum computer via QuLeaf, you need to ensure that the installed version of qcompute is above 3.0.0. You can use `pip install -U qcompute` to install the latest version of qcompute.\n",
"\n",
"In particular, qcompute requires protobuf version 4.21.1, while paddlepaddle requires protobuf versions 3.1.0 to 3.20.0. Therefore, you need to set environment variables to make paddlepaddle compatible with higher versions of protobuf.\n",
"\n",
"> Because paddlepaddle requires protobuf versions 3.1.0 through 3.20.0, all your python programs need to set environment variables so that they can import the paddlepaddle successfully. Therefore, if you don't need to use the qcompute, you can use `pip install protobuf==3.20.0` to ley you import the paddlepaddle without setting environment variable."
]
},
{
......@@ -36,6 +42,24 @@
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# Set the environment variable to make paddlepaddle compatible with the higher version of protobuf\n",
"import os\n",
"os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'python'"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Next, just use `paddle_quantum.set_backend('quleaf')` to set the backend of the quantum paddle to QuLeaf. In addition to that, we need to set the simulation method of the QuLeaf. If we use cloud computation power, we also need to enter the token, so the complete setup code is as follows."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import paddle_quantum\n",
"from QCompute import BackendName\n",
......@@ -79,7 +103,7 @@
},
{
"cell_type": "code",
"execution_count": 2,
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
......@@ -109,21 +133,21 @@
},
{
"cell_type": "code",
"execution_count": 4,
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The iter is 0, loss is 0.15198.\n",
"The iter is 10, loss is -0.76691.\n",
"The iter is 20, loss is -0.91600.\n",
"The iter is 30, loss is -0.97056.\n",
"The iter is 40, loss is -1.05518.\n",
"The iter is 50, loss is -1.13397.\n",
"The iter is 60, loss is -1.12326.\n",
"The iter is 70, loss is -1.13693.\n",
"The iter is 0, loss is -0.02081.\n",
"The iter is 10, loss is -0.54088.\n",
"The iter is 20, loss is -0.83405.\n",
"The iter is 30, loss is -1.01126.\n",
"The iter is 40, loss is -1.10169.\n",
"The iter is 50, loss is -1.10362.\n",
"The iter is 60, loss is -1.11572.\n",
"The iter is 70, loss is -1.11396.\n",
"The theoretical value is -1.137283834485513.\n"
]
}
......@@ -167,7 +191,7 @@
"loss_func = paddle_quantum.loss.ExpecVal(hamiltonian, shots=10000)\n",
"# iterative training\n",
"num_itr = 80\n",
"for itr in range(0, num_itr):\n",
"for itr in range(num_itr):\n",
" state = circuit(init_state)\n",
" loss = loss_func(state)\n",
" loss.backward()\n",
......@@ -190,7 +214,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.8.0 ('paddle-quantum-dev')",
"display_name": "Python 3.8.0 ('temp')",
"language": "python",
"name": "python3"
},
......@@ -209,7 +233,7 @@
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "9043b12ec77a531919bc05f05830335d23baf822720cbea14b03018197d26545"
"hash": "73730e2524c172926674de584a45f4a289689f765fd1f4813f545a2476542e53"
}
}
},
......
......@@ -28,7 +28,6 @@ from .hamiltonian import Hamiltonian
from . import ansatz
from . import channel
from . import gate
from . import linalg
from . import locc
from . import loss
from . import mbqc
......@@ -41,9 +40,10 @@ from . import gradtool
from . import hamiltonian
from . import linalg
from . import qinfo
from . import qml
from . import shadow
from . import trotter
from . import visual
name = 'paddle_quantum'
__version__ = '2.2.1'
__version__ = '2.2.2'
此差异已折叠。
......@@ -26,6 +26,39 @@ from paddle_quantum.linalg import is_unitary
from typing import Callable, List, Any, Optional
def cir_decompose(cir: Circuit, trainable: Optional[bool] = False) -> Circuit:
r"""Decompose all layers of circuit into gates, and make all parameterized gates trainable if needed
Args:
cir: Target quantum circuit.
trainable: whether the decomposed parameterized gates are trainable
Returns:
A quantum circuit with same structure and parameters but all layers are decomposed into Gates.
Note:
This function does not support customized gates, such as oracle and control-oracle.
"""
gates_history = cir.gate_history
new_cir = Circuit()
for gate_info in gates_history:
gate_name = gate_info['gate']
qubits_idx = gate_info['which_qubits']
param = gate_info['theta']
# get gate function
if param is None:
getattr(new_cir, gate_name)(qubits_idx)
continue
if trainable:
param = param.reshape([1] + param.shape)
param = paddle.create_parameter(
shape=param.shape, dtype=param.dtype,
default_initializer=paddle.nn.initializer.Assign(param))
getattr(new_cir, gate_name)(qubits_idx, param=param)
return new_cir
class Inserter:
r"""Class for block insertion for the circuit.
"""
......@@ -125,7 +158,8 @@ class Inserter:
cir.insert(insert_ind + 5, RZ([qubit_j], param=theta[4]))
cir.insert(insert_ind + 6, RX([qubit_j], param=theta[5]))
cir.insert(insert_ind + 7, CNOT([qubit_i, qubit_j]))
return cir
return cir_decompose(cir, trainable=True)
@classmethod
def __count_qubit_gates(cls, cir: Circuit) -> np.ndarray:
......@@ -144,14 +178,13 @@ class Inserter:
history = cir.gate_history
for gate_info in history:
qubits_idx = gate_info["which_qubits"]
if gate_info["gate"] == "rz" or gate_info["gate"] == "rx":
if gate_info["gate"] in ["rz", "rx"]:
qubit_ind = qubits_idx
count_gates[qubit_ind] += 1
elif gate_info["gate"] == "cnot":
qubit_i = min(qubits_idx[0], qubits_idx[1])
qubit_j = max(qubits_idx[0], qubits_idx[1])
idx = (2 * cir.num_qubits - qubit_i) * \
(qubit_i + 1) // 2 + qubit_j - qubit_i - 1
idx = (2 * cir.num_qubits - qubit_i) * (qubit_i + 1) // 2 + qubit_j - qubit_i - 1
count_gates[idx] += 1
return count_gates
......@@ -179,18 +212,11 @@ class Simplifier:
cnot_qubits = history_i[0][0]["which_qubits"]
# find the other qubit
for j in cnot_qubits:
if j != i:
# check the CNOT is also in the front for the other qubit
if (
qubit_history[j][0][0]["gate"] == "cnot"
and qubit_history[j][0][0]["which_qubits"]
== cnot_qubits
):
count += 1
if count == 0:
return True
else:
return False
if j != i and \
qubit_history[j][0][0]["gate"] == "cnot" and \
qubit_history[j][0][0]["which_qubits"] == cnot_qubits:
count += 1
return count == 0
@classmethod
def __check_consec_cnot(cls, cir: Circuit) -> bool:
......@@ -216,16 +242,13 @@ class Simplifier:
):
cnot_qubits = history_i[j][0]["which_qubits"]
# get the other qubit
k = list(set(cnot_qubits).difference(set([i])))[0]
k = list(set(cnot_qubits).difference({i}))[0]
# check if the found consecutive cnots are also consecutive on the other qubit
history_k = qubit_history[k]
idx_k = history_k.index(history_i[j])
if history_k[idx_k + 1] == history_i[j + 1]:
count += 1
if count == 0:
return True
else:
return False
return count == 0
@classmethod
def __check_rz_init(cls, cir: Circuit) -> bool:
......@@ -243,12 +266,9 @@ class Simplifier:
history_i = qubit_history[i]
if not history_i:
continue
if history_i[0][0]["gate"] == "z" or history_i[0][0]["gate"] == "rz":
if history_i[0][0]["gate"] in ["z", "rz"]:
count += 1
if count == 0:
return True
else:
return False
return count == 0
@classmethod
def __check_repeated_rotations(cls, cir: Circuit) -> bool:
......@@ -275,10 +295,7 @@ class Simplifier:
and history_i[j + 1][0]["gate"] == "rz"
):
count += 1
if count == 0:
return True
else:
return False
return count == 0
@classmethod
def __check_4_consec_rotations(cls, cir: Circuit) -> bool:
......@@ -309,10 +326,7 @@ class Simplifier:
and history_i[j + 3][0]["gate"] == "rx"
):
count += 1
if count == 0:
return True
else:
return False
return count == 0
@classmethod
def __check_rz_cnot_rz_rx_cnot_rx(cls, cir: Circuit) -> bool:
......@@ -344,10 +358,7 @@ class Simplifier:
and history_i[j + 1][0]["which_qubits"][1] == i
):
count += 1
if count == 0:
return True
else:
return False
return count == 0
@classmethod
def __rule_1(cls, cir: Circuit) -> Circuit:
......@@ -369,15 +380,11 @@ class Simplifier:
cnot_qubits = history_i[0][0]["which_qubits"]
# find the other qubit
for j in cnot_qubits:
if j != i:
# check the CNOT is also in the front for the other qubit
if (
qubit_history[j][0][0]["gate"] == "cnot"
and qubit_history[j][0][0]["which_qubits"]
== cnot_qubits
):
# delete the gate
cir.pop(qubit_history[j][0][1])
if j != i and \
qubit_history[j][0][0]["gate"] == "cnot" and \
qubit_history[j][0][0]["which_qubits"] == cnot_qubits:
# delete the gate
cir.pop(qubit_history[j][0][1])
qubit_history = cir.qubit_history
history_i = cir.qubit_history[i]
return cir
......@@ -409,7 +416,7 @@ class Simplifier:
):
cnot_qubits = history_i[j][0]["which_qubits"]
# get the other qubit
k = list(set(cnot_qubits).difference(set([i])))[0]
k = list(set(cnot_qubits).difference({i}))[0]
# check if the found consecutive cnots are also consecutive on the other qubit
history_k = qubit_history[k]
idx_k = history_k.index(history_i[j])
......@@ -437,7 +444,7 @@ class Simplifier:
history_i = cir.qubit_history[i]
if not history_i:
continue
if history_i[0][0]["gate"] == "z" or history_i[0][0]["gate"] == "rz":
if history_i[0][0]["gate"] in ["z", "rz"]:
# delete from history
cir.pop(history_i[0][1])
return cir
......@@ -709,41 +716,8 @@ class Simplifier:
cir = cls.__rule_5(cir)
cir = cls.__rule_6(cir)
return cir
def cir_decompose(cir: Circuit, trainable: Optional[bool] = False) -> Circuit:
r"""Decompose all layers of circuit into gates, and make all parameterized gates trainable if needed
Args:
cir: Target quantum circuit.
trainable: whether the decomposed parameterized gates are trainable
Returns:
A quantum circuit with same structure and parameters but all layers are decomposed into Gates.
Note:
This function does not support customized gates, such as oracle and control-oracle.
"""
gates_history = cir.gate_history
new_cir = Circuit()
for gate_info in gates_history:
gate_name = gate_info['gate']
qubits_idx = gate_info['which_qubits']
param = gate_info['theta']
# get gate function
if param is None:
getattr(new_cir, gate_name)(qubits_idx)
continue
if trainable:
param = param.reshape([1] + param.shape)
param = paddle.create_parameter(
shape=param.shape, dtype=param.dtype,
default_initializer=paddle.nn.initializer.Assign(param))
getattr(new_cir, gate_name)(qubits_idx, param=param)
return new_cir
return cir_decompose(cir, trainable=True)
class VAns:
r"""Class of Variable Ansatz.
......@@ -835,14 +809,13 @@ class VAns:
itr_loss = self.optimization(self.cir)
self.loss = itr_loss
else: # insert + simplification
# Insert
new_cir = cir_decompose(self.cir, trainable=True)
new_cir = self.cir
new_cir = Inserter.insert_identities(
new_cir, self.insert_rate, self.epsilon)
new_cir = Simplifier.simplify_circuit(
new_cir, self.zero_init_state)
itr_loss = self.optimization(new_cir)
relative_diff = (itr_loss - self.loss) / abs(itr_loss)
......@@ -879,8 +852,6 @@ class VAns:
Returns:
Optimized loss.
"""
cir = cir_decompose(cir, trainable=True)
opt = paddle.optimizer.Adam(
learning_rate=self.LR, parameters=cir.parameters())
......
......@@ -28,5 +28,7 @@ from .common import Depolarizing
from .common import PauliChannel
from .common import ResetChannel
from .common import ThermalRelaxation
from .common import MixedUnitaryChannel
from .custom import KrausRepr
from .custom import ChoiRepr
from .custom import StinespringRepr
......@@ -19,7 +19,8 @@ The source file of the classes for several quantum channel.
import paddle
import paddle_quantum
from paddle_quantum.intrinsic import _format_qubits_idx
from ..intrinsic import _format_qubits_idx
from ..qinfo import kraus_oper_random
from .base import Channel
from . import functional
from ..backend import Backend
......@@ -47,10 +48,7 @@ class BitFlip(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(prob, float):
self.prob = paddle.to_tensor(prob)
else:
self.prob = prob
self.prob = paddle.to_tensor(prob) if isinstance(prob, (int, float)) else prob
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -81,10 +79,7 @@ class PhaseFlip(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(prob, float):
self.prob = paddle.to_tensor(prob)
else:
self.prob = prob
self.prob = paddle.to_tensor(prob) if isinstance(prob, (int, float)) else prob
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -115,10 +110,7 @@ class BitPhaseFlip(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(prob, float):
self.prob = paddle.to_tensor(prob)
else:
self.prob = prob
self.prob = paddle.to_tensor(prob) if isinstance(prob, (int, float)) else prob
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -157,10 +149,7 @@ class AmplitudeDamping(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(gamma, float):
self.gamma = paddle.to_tensor(gamma)
else:
self.gamma = gamma
self.gamma = paddle.to_tensor(gamma) if isinstance(gamma, (int, float)) else gamma
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -198,14 +187,8 @@ class GeneralizedAmplitudeDamping(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(prob, float):
self.prob = paddle.to_tensor(prob)
else:
self.prob = prob
if isinstance(gamma, float):
self.gamma = paddle.to_tensor(gamma)
else:
self.gamma = gamma
self.prob = paddle.to_tensor(prob) if isinstance(prob, (int, float)) else prob
self.gamma = paddle.to_tensor(gamma) if isinstance(gamma, (int, float)) else gamma
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -245,10 +228,7 @@ class PhaseDamping(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(gamma, float):
self.gamma = paddle.to_tensor(gamma)
else:
self.gamma = gamma
self.gamma = paddle.to_tensor(gamma) if isinstance(gamma, (int, float)) else gamma
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -265,15 +245,22 @@ class Depolarizing(Channel):
.. math::
E_0 = \sqrt{1-p} I,
E_1 = \sqrt{p/3} X,
E_2 = \sqrt{p/3} Y,
E_3 = \sqrt{p/3} Z.
E_0 = \sqrt{1-3p/4} I,
E_1 = \sqrt{p/4} X,
E_2 = \sqrt{p/4} Y,
E_3 = \sqrt{p/4} Z.
Args:
prob: Parameter of the depolarizing channels. Its value should be in the range :math:`[0, 1]`.
qubits_idx: Indices of the qubits on which the channels act. Defaults to ``'full'``.
num_qubits: Total number of qubits. Defaults to ``None``.
Note:
The implementation logic for this feature has been updated.
The current version refers to formula (8.102) in Quantum Computation and Quantum Information 10th
edition by M.A.Nielsen and I.L.Chuang.
Reference: Nielsen, M., & Chuang, I. (2010). Quantum Computation and Quantum Information: 10th
Anniversary Edition. Cambridge: Cambridge University Press. doi:10.1017/CBO9780511976667
"""
def __init__(
self, prob: Union[paddle.Tensor, float],
......@@ -281,10 +268,7 @@ class Depolarizing(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(prob, float):
self.prob = paddle.to_tensor(prob)
else:
self.prob = prob
self.prob = paddle.to_tensor(prob) if isinstance(prob, (int, float)) else prob
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -312,10 +296,7 @@ class PauliChannel(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(prob, Iterable):
self.prob = paddle.to_tensor(prob)
else:
self.prob = prob
self.prob = paddle.to_tensor(prob) if isinstance(prob, Iterable) else prob
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -370,10 +351,7 @@ class ResetChannel(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(prob, Iterable):
self.prob = paddle.to_tensor(prob)
else:
self.prob = prob
self.prob = paddle.to_tensor(prob) if isinstance(prob, Iterable) else prob
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -403,14 +381,8 @@ class ThermalRelaxation(Channel):
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
if isinstance(const_t, float):
self.const_t = paddle.to_tensor(const_t)
else:
self.const_t = const_t
if isinstance(exec_time, float):
self.exec_time = paddle.to_tensor(exec_time)
else:
self.exec_time = exec_time
self.const_t = paddle.to_tensor(const_t) if isinstance(const_t, (int, float)) else const_t
self.exec_time = paddle.to_tensor(exec_time) if isinstance(exec_time, (int, float)) else exec_time
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
......@@ -419,3 +391,35 @@ class ThermalRelaxation(Channel):
state = functional.thermal_relaxation(
state, self.const_t, self.exec_time, qubit_idx, self.dtype, self.backend)
return state
class MixedUnitaryChannel(Channel):
r"""A collection of mixed unitary channels.
Such a channel's Kraus operators are randomly generated unitaries times related probabilities
.. math::
N(\rho) = \sum_{i} p_{i} U_{i} \rho U_{i}^{\dagger}
Args:
num_unitary: The amount of random unitaries to be generated.
qubits_idx: Indices of the qubits on which the channels act. Defaults to ``'full'``.
num_qubits: Total number of qubits. Defaults to ``None``.
Note:
The probability distribution of unitaries is set to be uniform distribution.
"""
def __init__(
self, num_unitary: int,
qubits_idx: Union[Iterable[int], int, str] = 'full', num_qubits: int = None
):
super().__init__()
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
self.kraus_oper = kraus_oper_random(1, num_unitary)
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
if self.backend == Backend.QuLeaf and state.backend == Backend.QuLeaf:
raise NotImplementedError
for qubit_idx in self.qubits_idx:
state = functional.kraus_repr(state, self.kraus_oper, qubit_idx, self.dtype, self.backend)
return state
......@@ -19,11 +19,13 @@ The source file of the classes for custom quantum channels.
import math
import paddle
import warnings
from typing import Union, Iterable
import paddle_quantum
from .base import Channel
from paddle_quantum.intrinsic import _format_qubits_idx
from . import functional
from typing import Union, Iterable
from ..intrinsic import _format_qubits_idx
class KrausRepr(Channel):
......@@ -35,23 +37,94 @@ class KrausRepr(Channel):
num_qubits: Total number of qubits. Defaults to ``None``.
"""
def __init__(
self, kraus_oper: Iterable[paddle.Tensor],
self, kraus_oper: Union[paddle.Tensor, Iterable[paddle.Tensor]],
qubits_idx: Union[Iterable[Iterable[int]], Iterable[int], int],
num_qubits: int = None
):
# TODO: need to check whether the input is legal
super().__init__()
num_acted_qubits = int(math.log2(kraus_oper[0].shape[0]))
assert 2 ** num_acted_qubits == kraus_oper[0].shape[0], "The length of oracle should be integer power of 2."
self.kraus_oper = kraus_oper
is_single_qubit = True if num_acted_qubits == 1 else False
self.kraus_oper = [oper.cast(self.dtype) for oper in kraus_oper] if isinstance(kraus_oper, Iterable) else [kraus_oper.cast(self.dtype)]
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits, num_acted_qubits)
# sanity check
dimension = 2 ** num_acted_qubits
oper_sum = paddle.zeros([dimension, dimension]).cast(self.dtype)
for oper in self.kraus_oper:
oper_sum = oper_sum + oper @ paddle.conj(oper.T)
err = paddle.norm(paddle.abs(oper_sum - paddle.eye(dimension).cast(self.dtype))).item()
if err > min(1e-6 * dimension * len(kraus_oper), 0.01):
warnings.warn(
f"\nThe input data may not be a Kraus representation of a channel: norm(sum(E * E^d) - I) = {err}.", UserWarning)
def forward(self, state: 'paddle_quantum.State') -> 'paddle_quantum.State':
def __matmul__(self, other: 'KrausRepr') -> 'KrausRepr':
r"""Composition between channels with Kraus representations
"""
assert self.qubits_idx == other.qubits_idx, \
f"Two channels should have the same qubit indices to composite: received {self.qubits_idx} and {other.qubits_idx}"
if not isinstance(other, KrausRepr):
raise NotImplementedError(
f"does not support the composition between KrausRepr and {type(other)}")
new_kraus_oper = []
for this_kraus in self.kraus_oper:
new_kraus_oper.extend([this_kraus @ other_kraus for other_kraus in other.kraus_oper])
return KrausRepr(new_kraus_oper, self.qubits_idx)
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
for qubits_idx in self.qubits_idx:
state = functional.kraus_repr(state, self.kraus_oper, qubits_idx, self.dtype, self.backend)
return state
class ChoiRepr(Channel):
pass
def __init__(
self,
choi_oper: paddle.Tensor,
qubits_idx: Union[Iterable[Iterable[int]], Iterable[int], int],
num_qubits: int = None
):
super().__init__()
num_acted_qubits = int(math.log2(choi_oper.shape[0]) / 2)
assert 2 ** (2 * num_acted_qubits) == choi_oper.shape[0], "The length of oracle should be integer power of 2."
self.choi_oper = choi_oper
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits, num_acted_qubits)
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
for qubits_idx in self.qubits_idx:
state = functional.choi_repr(
state,
self.choi_oper,
qubits_idx,
self.dtype,
self.backend
)
return state
class StinespringRepr(Channel):
def __init__(
self,
stinespring_matrix: paddle.Tensor,
qubits_idx: Union[Iterable[Iterable[int]], Iterable[int], int],
num_qubits: int = None
):
super().__init__()
num_acted_qubits = int(math.log2(stinespring_matrix.shape[1]))
dim_ancilla = stinespring_matrix.shape[0] // stinespring_matrix.shape[1]
dim_act = stinespring_matrix.shape[1]
assert dim_act * dim_ancilla == stinespring_matrix.shape[0], 'The width of stinespring matrix should be the factor of its height'
self.stinespring_matrix = stinespring_matrix
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits, num_acted_qubits)
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
for qubits_idx in self.qubits_idx:
state = functional.stinespring_repr(
state,
self.stinespring_matrix,
qubits_idx,
self.dtype,
self.backend
)
return state
......@@ -29,3 +29,4 @@ from .common import reset_channel
from .common import thermal_relaxation
from .common import kraus_repr
from .common import choi_repr
from .common import stinespring_repr
......@@ -20,7 +20,7 @@ The module of the quantum gates.
from . import functional
from .base import Gate, ParamGate
from .clifford import Clifford, compose_clifford_circuit
from .single_qubit_gate import H, S, T, X, Y, Z, P, RX, RY, RZ, U3
from .single_qubit_gate import H, S, Sdg, T, Tdg, X, Y, Z, P, RX, RY, RZ, U3
from .multi_qubit_gate import CNOT, CX, CY, CZ, SWAP
from .multi_qubit_gate import CP, CRX, CRY, CRZ, CU, RXX, RYY, RZZ
from .multi_qubit_gate import MS, CSWAP, Toffoli
......
......@@ -19,10 +19,13 @@ The source file of the basic class for the quantum gates.
import paddle
import paddle_quantum
from typing import Union, List, Iterable
from typing import Union, List, Iterable, Optional, Any
from paddle_quantum.gate.functional.single_qubit_gate import x
from ..intrinsic import _get_float_dtype
from math import pi
from .functional.visual import _base_gate_display, _base_param_gate_display
import matplotlib
class Gate(paddle_quantum.Operator):
r"""Base class for quantum gates.
......@@ -40,8 +43,12 @@ class Gate(paddle_quantum.Operator):
):
super().__init__(backend, dtype, name_scope)
self.depth = depth
self.gate_name = None
self.gate_info = {
'gatename': None,
'texname': None,
'plot_width': None,
}
def forward(self, *inputs, **kwargs):
raise NotImplementedError
......@@ -58,11 +65,34 @@ class Gate(paddle_quantum.Operator):
"""
gate_history = []
for _ in range(0, self.depth):
for _ in range(self.depth):
for qubit_idx in self.qubits_idx:
gate_info = {'gate': self.gate_name, 'which_qubits': qubit_idx, 'theta': None}
gate_info = {'gate': self.gate_info['gatename'], 'which_qubits': qubit_idx, 'theta': None}
gate_history.append(gate_info)
self.gate_history = gate_history
def set_gate_info(self, **kwargs: Any) -> None:
r'''the interface to set `self.gate_info`
Args:
kwargs: parameters to set `self.gate_info`
'''
self.gate_info.update(kwargs)
def display_in_circuit(self, ax: matplotlib.axes.Axes, x: float,) -> float:
r'''The display function called by circuit instance when plotting.
Args:
ax: the ``matplotlib.axes.Axes`` instance
x: the start horizontal position
Returns:
the total width occupied
Note:
Users could overload this function for custom display.
'''
return _base_gate_display(self, ax, x)
class ParamGate(Gate):
......@@ -88,7 +118,7 @@ class ParamGate(Gate):
"""
float_dtype = _get_float_dtype(self.dtype)
if param is None:
theta = self.create_parameter(
shape=param_shape, dtype=float_dtype,
......@@ -97,16 +127,16 @@ class ParamGate(Gate):
self.add_parameter('theta', theta)
elif isinstance(param, paddle.fluid.framework.ParamBase):
assert param.shape == param_shape, "received: " + str(param.shape) + " expect: " + str(param_shape)
assert param.shape == param_shape, f"received: {str(param.shape)} expect: {param_shape}"
self.add_parameter('theta', param)
elif isinstance(param, paddle.Tensor):
param = param.reshape(param_shape)
self.theta = param
elif isinstance(param, float):
elif isinstance(param, (int, float)):
self.theta = paddle.ones(param_shape, dtype=float_dtype) * param
else: # when param is a list of float
self.theta = paddle.to_tensor(param, dtype=float_dtype).reshape(param_shape)
......@@ -115,12 +145,27 @@ class ParamGate(Gate):
"""
gate_history = []
for depth_idx in range(0, self.depth):
for depth_idx in range(self.depth):
for idx, qubit_idx in enumerate(self.qubits_idx):
if self.param_sharing:
param = self.theta[depth_idx]
else:
param = self.theta[depth_idx][idx]
gate_info = {'gate': self.gate_name, 'which_qubits': qubit_idx, 'theta': param}
gate_info = {'gate': self.gate_info['gatename'], 'which_qubits': qubit_idx, 'theta': param}
gate_history.append(gate_info)
self.gate_history = gate_history
def display_in_circuit(self, ax: matplotlib.axes.Axes, x: float,) -> float:
r'''The display function called by circuit instance when plotting.
Argrs:
ax: the ``matplotlib.axes.Axes`` instance
x: the start horizontal position
Returns:
the total width occupied
Note:
Users could overload this function for custom display.
'''
return _base_param_gate_display(self, ax, x)
\ No newline at end of file
......@@ -18,13 +18,16 @@ The source file of the oracle class and the control oracle class.
"""
import math
import matplotlib
import paddle
import paddle_quantum
import warnings
import paddle_quantum as pq
from . import functional
from .base import Gate
from paddle_quantum.intrinsic import _format_qubits_idx
from ..intrinsic import _format_qubits_idx
from typing import Union, Iterable
from paddle_quantum.linalg import is_unitary
from .functional.visual import _c_oracle_like_display, _oracle_like_display
class Oracle(Gate):
......@@ -38,22 +41,38 @@ class Oracle(Gate):
"""
def __init__(
self, oracle: paddle.Tensor, qubits_idx: Union[Iterable[Iterable[int]], Iterable[int], int],
num_qubits: int = None, depth: int = 1, gate_name: str = 'O'
num_qubits: int = None, depth: int = 1, gate_info: dict = None
):
super().__init__(depth)
oracle = oracle.cast(paddle_quantum.get_dtype())
assert is_unitary(oracle), "the input oracle must be a unitary matrix"
num_acted_qubits = int(math.log2(oracle.shape[0]))
self.oracle = paddle.cast(oracle, paddle_quantum.get_dtype())
complex_dtype = pq.get_dtype()
oracle = oracle.cast(complex_dtype)
dimension = oracle.shape[0]
err = paddle.norm(paddle.abs(oracle @ paddle.conj(oracle.T) - paddle.cast(paddle.eye(dimension), complex_dtype))).item()
if err > min(1e-6 * dimension, 0.01):
warnings.warn(
f"\nThe input oracle may not be a unitary: norm(U * U^d - I) = {err}.", UserWarning)
num_acted_qubits = int(math.log2(dimension))
self.oracle = oracle
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits, num_acted_qubits)
self.gate_name = gate_name
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
for _ in range(0, self.depth):
self.gate_info = {
'gatename': 'O',
'texname': r'$O$',
'plot_width': 0.6,
}
if gate_info:
self.gate_info.update(gate_info)
def forward(self, state: pq.State) -> pq.State:
for _ in range(self.depth):
for qubits_idx in self.qubits_idx:
state = functional.oracle(state, self.oracle, qubits_idx, self.backend)
return state
def display_in_circuit(self, ax: matplotlib.axes.Axes, x: float,) -> float:
return _oracle_like_display(self, ax, x)
class ControlOracle(Gate):
......@@ -67,27 +86,40 @@ class ControlOracle(Gate):
"""
def __init__(
self, oracle: paddle.Tensor, qubits_idx: Union[Iterable[Iterable[int]], Iterable[int]],
num_qubits: int = None, depth: int = 1, gate_name: str = 'cO'
num_qubits: int = None, depth: int = 1, gate_info: dict = None
) -> None:
super().__init__(depth)
complex_dtype = paddle_quantum.get_dtype()
complex_dtype = pq.get_dtype()
oracle = oracle.cast(complex_dtype)
assert is_unitary(oracle), "the input oracle must be a unitary matrix"
num_acted_qubits = int(math.log2(oracle.shape[0]))
# 暂时只支持单控制位
dimension = oracle.shape[0]
err = paddle.norm(paddle.abs(oracle @ paddle.conj(oracle.T) - paddle.cast(paddle.eye(dimension), complex_dtype))).item()
if err > min(1e-6 * dimension, 0.01):
warnings.warn(
f"\nThe input oracle may not be a unitary: norm(U * U^d - I) = {err}.", UserWarning)
num_acted_qubits = int(math.log2(dimension))
oracle = (
paddle.kron(paddle.to_tensor([[1.0, 0], [0, 0]], dtype=complex_dtype), paddle.eye(2 ** num_acted_qubits)) +
paddle.kron(paddle.to_tensor([[0.0, 0], [0, 1]], dtype=complex_dtype), oracle)
)
num_acted_qubits = num_acted_qubits + 1
num_acted_qubits += 1
self.oracle = oracle
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits, num_acted_qubits)
self.gate_name = gate_name
def forward(self, state: paddle_quantum.State) -> paddle_quantum.State:
for _ in range(0, self.depth):
self.gate_info = {
'gatename': 'cO',
'texname': r'$O$',
'plot_width': 0.6,
}
if gate_info:
self.gate_info.update(gate_info)
def forward(self, state: pq.State) -> pq.State:
for _ in range(self.depth):
for qubits_idx in self.qubits_idx:
state = functional.oracle(state, self.oracle, qubits_idx, self.backend)
return state
def display_in_circuit(self, ax: matplotlib.axes.Axes, x: float,) -> float:
return _c_oracle_like_display(self, ax, x)
......@@ -42,7 +42,7 @@ class BasisEncoding(Gate):
super().__init__()
self.num_qubits = num_qubits
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
self.gate_name = 'BasisEnc'
self.gate_info['gatename'] = 'BasisEnc'
def forward(self, feature: paddle.Tensor, state: 'paddle_quantum.State' = None) -> 'paddle_quantum.State':
if state is None:
......@@ -78,7 +78,7 @@ class AmplitudeEncoding(Gate):
super().__init__()
self.num_qubits = num_qubits
self.qubits_idx = _format_qubits_idx(qubits_idx, num_qubits)
self.gate_name = 'AmpEnc'
self.gate_info['gatename'] = 'AmpEnc'
def forward(self, feature: paddle.Tensor) -> 'paddle_quantum.State':
def calc_location(location_of_bits_list):
......@@ -157,7 +157,7 @@ class AngleEncoding(Gate):
feature = paddle.flatten(feature)
self.feature = feature
self.gate_name = 'AngleEnc'
self.gate_info['gatename'] = 'AngleEnc'
def forward(
self, state: 'paddle_quantum.State' = None, invert: bool = False
......@@ -206,7 +206,7 @@ class IQPEncoding(Gate):
feature = paddle.flatten(feature)
self.feature = feature
self.gate_name = 'IQPEnc'
self.gate_info['gatename'] = 'IQPEnc'
def forward(
self, state: paddle_quantum.State = None, invert: Optional[bool] = False
......
......@@ -19,7 +19,9 @@ The module that contains the functions of various quantum gates.
from .single_qubit_gate import h
from .single_qubit_gate import s
from .single_qubit_gate import sdg
from .single_qubit_gate import t
from .single_qubit_gate import tdg
from .single_qubit_gate import x
from .single_qubit_gate import y
from .single_qubit_gate import z
......
......@@ -71,6 +71,29 @@ def s(state: paddle_quantum.State, qubit_idx: int, dtype: str, backend: paddle_q
return transformed_state
def sdg(state: paddle_quantum.State, qubit_idx: int, dtype: str, backend: paddle_quantum.Backend) -> paddle_quantum.State:
r"""Apply an S dagger (inverse S) gate on the input state.
Args:
state: Input state.
qubit_idx: Index of the qubit on which the gate is applied.
dtype: Type of data.
backend: Backend on which the simulation is run.
Returns:
Output state.
"""
gate = [
[1, 0],
[0, -1j],
]
gate = paddle.to_tensor(gate, dtype=dtype)
state_data = simulation(state, gate, qubit_idx, state.num_qubits, backend)
transformed_state = state.clone()
transformed_state.data = state_data
return transformed_state
def t(state: paddle_quantum.State, qubit_idx: int, dtype: str, backend: paddle_quantum.Backend) -> paddle_quantum.State:
r"""Apply a T gate on the input state.
......@@ -93,6 +116,27 @@ def t(state: paddle_quantum.State, qubit_idx: int, dtype: str, backend: paddle_q
transformed_state.data = state_data
return transformed_state
def tdg(state: paddle_quantum.State, qubit_idx: int, dtype: str, backend: paddle_quantum.Backend) -> paddle_quantum.State:
r"""Apply a T dagger (inverse T) gate on the input state.
Args:
state: Input state.
qubit_idx: Index of the qubit on which the gate is applied.
dtype: Type of data.
backend: Backend on which the simulation is run.
Returns:
Output state.
"""
gate = [
[1, 0],
[0, math.cos(math.pi/4) - math.sin(math.pi/4) * 1j],
]
gate = paddle.to_tensor(gate, dtype=dtype)
state_data = simulation(state, gate, qubit_idx, state.num_qubits, backend)
transformed_state = state.clone()
transformed_state.data = state_data
return transformed_state
def x(state: paddle_quantum.State, qubit_idx: int, dtype: str, backend: paddle_quantum.Backend) -> paddle_quantum.State:
r"""Apply an X gate on the input state.
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -21,12 +21,16 @@ import numpy as np
import paddle
from typing import Union, Iterable, List
from .base import get_dtype
def _zero(dtype):
def _zero(dtype = None):
dtype = get_dtype() if dtype is None else dtype
return paddle.to_tensor(0, dtype=dtype)
def _one(dtype):
def _one(dtype = None):
dtype = get_dtype() if dtype is None else dtype
return paddle.to_tensor(1, dtype=dtype)
......@@ -65,6 +69,7 @@ def _format_qubits_idx(
raise TypeError(
"The qubits_idx should be iterable such as list, tuple, and so on whose elements are all integers."
"And the length of acted_qubits should be consistent with the corresponding gate."
f"\n Received qubits_idx type {type(qubits_idx)}, qubits # {len(qubits_idx)}, gate dimension {num_acted_qubits}"
)
return qubits_idx
......
此差异已折叠。
......@@ -18,7 +18,6 @@ The source file of the LoccAnsatz class.
"""
import collections
from matplotlib import docstring
import paddle
import paddle_quantum
from ..gate import H, S, T, X, Y, Z, P, RX, RY, RZ, U3
......
此差异已折叠。
此差异已折叠。
# !/usr/bin/env python3
# Copyright (c) 2022 Institute for Quantum Computing, Baidu Inc. 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.
r"""
The quantum machine learning module.
"""
此差异已折叠。
# !/usr/bin/env python3
# Copyright (c) 2021 Institute for Quantum Computing, Baidu Inc. 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.
r"""
The module of quantum phase processing.
"""
from .laurent import *
from .angles import *
from .utils import *
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -17,7 +17,8 @@ r"""
The module of the quantum state.
"""
from .state import State
from .state import State, is_state_vector, is_density_matrix
from .state import _type_fetch, _type_transform
from .common import zero_state
from .common import computational_basis
from .common import bell_state
......
此差异已折叠。
......@@ -29,6 +29,7 @@ from typing import Optional, Union, Tuple, List
import os
def plot_state_in_bloch_sphere(
state: List[paddle_quantum.State],
show_arrow: Optional[bool] = False,
......@@ -832,3 +833,4 @@ def __input_args_dtype_check(show_arrow: bool, save_gif: bool, filename: str, vi
), 'the type of "view_angle[0]" and "view_angle[1]" should be "int".'
if view_dist is not None:
assert type(view_dist) == int, 'the type of "view_dist" should be "int".'
paddlepaddle<=2.3.0
scipy>=1.8.1
protobuf<=3.20.1
networkx>=2.5
paddlepaddle>=2.2.0, <=2.3.0
protobuf>=3.1.0, <=3.20.1
qcompute
matplotlib
networkx>=2.5
matplotlib>=3.3.0
scipy
tqdm
openfermion
pyscf; platform_system == "Linux" or platform_system == "Darwin"
scikit-learn
opencv-python
cvxpy
rich
......@@ -24,7 +24,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
setuptools.setup(
name='paddle-quantum',
version='2.2.1',
version='2.2.2',
author='Institute for Quantum Computing, Baidu INC.',
author_email='qml@baidu.com',
description='Paddle Quantum is a quantum machine learning (QML) toolkit developed based on Baidu PaddlePaddle.',
......@@ -44,7 +44,9 @@ setuptools.setup(
'paddle_quantum.operator',
'paddle_quantum.state',
'paddle_quantum.qchem',
'paddle_quantum.qml',
'paddle_quantum.qsvt',
'paddle_quantum.qpp',
'paddle_quantum.mbqc',
'paddle_quantum.GIBBS',
'paddle_quantum.GIBBS.example',
......@@ -79,18 +81,20 @@ setuptools.setup(
'paddle_quantum.mbqc.VQSVD.example': ['*.txt'],
},
install_requires=[
'paddlepaddle<=2.3.0',
'scipy>=1.8.1',
'protobuf<=3.20.1',
'networkx>=2.5',
'paddlepaddle>=2.2.0, <=2.3.0',
'protobuf>=3.1.0, <=3.20.1',
'qcompute',
'networkx>=2.5',
'matplotlib>=3.3.0',
'scipy',
'tqdm',
'openfermion',
'pyscf; platform_system == "Linux" or platform_system == "Darwin"',
'opencv-python',
'scikit-learn',
'fastdtw',
'cvxpy',
'rich',
],
python_requires='>=3.6, <4',
classifiers=[
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册