Repository: mit-han-lab/torchquantum (language: python)

Issue:
add supports for more basic operations and layers
In order to enrich the supported operations of tq, we need your help on adding more functionalities. 

Please firstly identity the gates that have not been supported by torchquantum, you can find them by having a look at other frameworks such as Qiskit, Cirq etc. You can identity the gates that not supported by looking at qiskit.circuit.library.
Such as the SdG gate:
[SdgGate](https://qiskit.org/documentation/stubs/qiskit.circuit.library.SdgGate.html#qiskit.circuit.library.SdgGate)

For the simplest non-parameterized gates, you need firstly add their unitary matrix to tq.functional file: https://github.com/mit-han-lab/torchquantum/blob/8d06a998a6d35374907c5e75a347d187e837b8cc/torchquantum/functional.py#L1104 and also add their functions. Then you can add a class to the tq.operators files and finally add test function to test/test_op.py. You may create new test files.

You may also implement other template layers according to qiskit.circuit.library. https://qiskit.org/documentation/apidoc/circuit_library.html

Please let us know if you have any questions or need any instructions!


Bug Fixes and Full Standard Gates
Same as https://github.com/mit-han-lab/torchquantum/pull/180 without the formatting fixes.
add supports for more basic operations and layers
In order to enrich the supported operations of tq, we need your help on adding more functionalities. 

Please firstly identity the gates that have not been supported by torchquantum, you can find them by having a look at other frameworks such as Qiskit, Cirq etc. You can identity the gates that not supported by looking at qiskit.circuit.library.
Such as the SdG gate:
[SdgGate](https://qiskit.org/documentation/stubs/qiskit.circuit.library.SdgGate.html#qiskit.circuit.library.SdgGate)

For the simplest non-parameterized gates, you need firstly add their unitary matrix to tq.functional file: https://github.com/mit-han-lab/torchquantum/blob/8d06a998a6d35374907c5e75a347d187e837b8cc/torchquantum/functional.py#L1104 and also add their functions. Then you can add a class to the tq.operators files and finally add test function to test/test_op.py. You may create new test files.

You may also implement other template layers according to qiskit.circuit.library. https://qiskit.org/documentation/apidoc/circuit_library.html

Please let us know if you have any questions or need any instructions!




Discussion / hints:

Fix patch:
diff --git a/README.md b/README.md
index e7236829..57501fb3 100644
--- a/README.md
+++ b/README.md
@@ -104,7 +104,7 @@ op(qdev, wires=0)
 print(qdev)
 
 # obtain the qasm string
-from torchquantum.plugins import op_history2qasm
+from torchquantum.plugin import op_history2qasm
 print(op_history2qasm(qdev.n_wires, qdev.op_history))
 
 # measure the state on z basis
diff --git a/docs/source/conf.py b/docs/source/conf.py
index 59d7f757..86fbdc7a 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 # Configuration file for the Sphinx documentation builder.
 
 # If extensions (or modules to document with autodoc) are in another directory,
diff --git a/docs/source/index.rst b/docs/source/index.rst
index cb5df6b1..a1a4f08a 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -127,7 +127,7 @@ Basic Usage
    print(qdev)
 
    # obtain the qasm string
-   from torchquantum.plugins import op_history2qasm
+   from torchquantum.plugin import op_history2qasm
    print(op_history2qasm(qdev.n_wires, qdev.op_history))
 
    # measure the state on z basis
diff --git a/examples/ICCAD22_tutorial/sec1_basic.ipynb b/examples/ICCAD22_tutorial/sec1_basic.ipynb
index c41a8f29..6ac74155 100644
--- a/examples/ICCAD22_tutorial/sec1_basic.ipynb
+++ b/examples/ICCAD22_tutorial/sec1_basic.ipynb
@@ -730,7 +730,7 @@
    "cell_type": "code",
    "source": [
     "# easy conversion to qiskit\n",
-    "from torchquantum.plugins.qiskit_plugin import tq2qiskit\n",
+    "from torchquantum.plugin.qiskit_plugin import tq2qiskit\n",
     "\n",
     "circ = tq2qiskit(q_dev, model)\n",
     "circ.draw('mpl')"
@@ -1763,7 +1763,7 @@
     "import torchquantum as tq\n",
     "import torchquantum.functional as tqf\n",
     "\n",
-    "from torchquantum.plugins import (tq2qiskit_expand_params,\n",
+    "from torchquantum.plugin import (tq2qiskit_expand_params,\n",
     "                                  tq2qiskit,\n",
     "                                  tq2qiskit_measurement,\n",
     "                                  qiskit_assemble_circs)\n",
@@ -1987,7 +1987,7 @@
     "    # run on Qiskit simulator and real Quantum Computers\n",
     "    try:\n",
     "        from qiskit import IBMQ\n",
-    "        from torchquantum.plugins import QiskitProcessor\n",
+    "        from torchquantum.plugin import QiskitProcessor\n",
     "\n",
     "        # firstly perform simulate\n",
     "        print(f\"\\nTest with Qiskit Simulator\")\n",
diff --git a/examples/ICCAD22_tutorial/sec3_gate.ipynb b/examples/ICCAD22_tutorial/sec3_gate.ipynb
index 03b3f7db..64205355 100644
--- a/examples/ICCAD22_tutorial/sec3_gate.ipynb
+++ b/examples/ICCAD22_tutorial/sec3_gate.ipynb
@@ -11786,7 +11786,7 @@
     "from torchquantum.datasets import MNIST\n",
     "import torch.optim as optim\n",
     "\n",
-    "from torchquantum.plugins import tq2qiskit, qiskit2tq\n",
+    "from torchquantum.plugin import tq2qiskit, qiskit2tq\n",
     "from torchquantum.utils import (build_module_from_op_list,\n",
     "                                build_module_op_list,\n",
     "                                get_v_c_reg_mapping,\n",
@@ -12494,7 +12494,7 @@
     }
    ],
    "source": [
-    "from torchquantum.plugins import tq2qiskit\n",
+    "from torchquantum.plugin import tq2qiskit\n",
     "gene_choice = model.arch_space\n",
     "gene_len = len(gene_choice)\n",
     "n_samples=1\n",
@@ -12535,7 +12535,7 @@
    },
    "outputs": [],
    "source": [
-    "from torchquantum.plugins import QiskitProcessor\n",
+    "from torchquantum.plugin import QiskitProcessor\n",
     "from qiskit import IBMQ\n",
     "IBMQ.save_account('0238b0afc0dc515fe7987b02706791d1719cb89b68befedc125eded0607e6e9e9f26d3eed482f66fdc45fdfceca3aab2edb9519d96b39e9c78040194b86e7858', overwrite=True)\n",
     "\n",
@@ -16233,7 +16233,7 @@
     "\n",
     "from torchquantum.datasets import MNIST\n",
     "from torch.optim.lr_scheduler import CosineAnnealingLR\n",
-    "from torchquantum.plugins import tq2qiskit, qiskit2tq\n",
+    "from torchquantum.plugin import tq2qiskit, qiskit2tq\n",
     "from torchquantum.utils import (build_module_from_op_list,\n",
     "                                build_module_op_list,\n",
     "                                get_v_c_reg_mapping,\n",
@@ -16241,7 +16241,7 @@
     "                                get_p_v_reg_mapping,\n",
     "                                get_cared_configs)\n",
     "\n",
-    "from torchquantum.plugins import QiskitProcessor\n",
+    "from torchquantum.plugin import QiskitProcessor\n",
     "\n",
     "import random\n",
     "import numpy as np"
@@ -17221,7 +17221,7 @@
     }
    },
    "source": [
-    "Train and valid the model on ibmq_quito. You need to import `QiskitProcessor` from `torchquantum.plugins` to create a processor that handles your access to real quantum computer. You can set whether use real quantum computer or qiskit's noise model, and the backend of your quantum computer. Call `model.set_qiskit_processor` to attach the processor to your model."
+    "Train and valid the model on ibmq_quito. You need to import `QiskitProcessor` from `torchquantum.plugin` to create a processor that handles your access to real quantum computer. You can set whether use real quantum computer or qiskit's noise model, and the backend of your quantum computer. Call `model.set_qiskit_processor` to attach the processor to your model."
    ]
   },
   {
@@ -17363,7 +17363,7 @@
     }
    ],
    "source": [
-    "from torchquantum.plugins import QiskitProcessor\n",
+    "from torchquantum.plugin import QiskitProcessor\n",
     "model = Q2Model().to(device)\n",
     "processor_real_qc = QiskitProcessor(use_real_qc=True, backend_name='ibmq_quito')\n",
     "model.set_qiskit_processor(processor_real_qc)\n",
@@ -18134,7 +18134,7 @@
    "cell_type": "code",
    "source": [
     "from qiskit.compiler.transpiler import transpile\n",
-    "from torchquantum.plugins import tq2qiskit, qiskit2tq\n",
+    "from torchquantum.plugin import tq2qiskit, qiskit2tq\n",
     "from torch.nn.parameter import Parameter\n",
     "\n",
     "def get_weight_from_model(model):\n",
@@ -18646,7 +18646,7 @@
    "cell_type": "code",
    "source": [
     "from qiskit.compiler.transpiler import transpile\n",
-    "from torchquantum.plugins import tq2qiskit, qiskit2tq\n",
+    "from torchquantum.plugin import tq2qiskit, qiskit2tq\n",
     "from torch.nn.parameter import Parameter\n",
     "from qiskit.test.mock import FakeValencia\n",
     "import matplotlib.pyplot as plt\n",
diff --git a/examples/PauliSumOp/pauli_sum_op.py b/examples/PauliSumOp/pauli_sum_op.py
index 05a13115..0a3ad808 100644
--- a/examples/PauliSumOp/pauli_sum_op.py
+++ b/examples/PauliSumOp/pauli_sum_op.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import argparse
 
diff --git a/examples/QCE22_tutorial/sec1_basic.ipynb b/examples/QCE22_tutorial/sec1_basic.ipynb
index 90abc75c..6400e2ee 100644
--- a/examples/QCE22_tutorial/sec1_basic.ipynb
+++ b/examples/QCE22_tutorial/sec1_basic.ipynb
@@ -730,7 +730,7 @@
    "cell_type": "code",
    "source": [
     "# easy conversion to qiskit\n",
-    "from torchquantum.plugins.qiskit_plugin import tq2qiskit\n",
+    "from torchquantum.plugin.qiskit_plugin import tq2qiskit\n",
     "\n",
     "circ = tq2qiskit(q_dev, model)\n",
     "circ.draw('mpl')"
@@ -779,8 +779,8 @@
    "cell_type": "code",
    "source": [
     "# easy deployment on real quantum machine\n",
-    "from torchquantum.plugins.qiskit_plugin import tq2qiskit\n",
-    "from torchquantum.plugins.qiskit_processor import QiskitProcessor\n",
+    "from torchquantum.plugin.qiskit_plugin import tq2qiskit\n",
+    "from torchquantum.plugin.qiskit_processor import QiskitProcessor\n",
     "from qiskit import IBMQ\n",
     "IBMQ.save_account('0238b0afc0dc515fe7987b02706791d1719cb89b68befedc125eded0607e6e9e9f26d3eed482f66fdc45fdfceca3aab2edb9519d96b39e9c78040194b86e7858', overwrite=True)\n",
     "\n",
@@ -1824,7 +1824,7 @@
     "import torchquantum as tq\n",
     "import torchquantum.functional as tqf\n",
     "\n",
-    "from torchquantum.plugins import (tq2qiskit_expand_params,\n",
+    "from torchquantum.plugin import (tq2qiskit_expand_params,\n",
     "                                  tq2qiskit,\n",
     "                                  tq2qiskit_measurement,\n",
     "                                  qiskit_assemble_circs)\n",
@@ -2048,7 +2048,7 @@
     "    # run on Qiskit simulator and real Quantum Computers\n",
     "    try:\n",
     "        from qiskit import IBMQ\n",
-    "        from torchquantum.plugins import QiskitProcessor\n",
+    "        from torchquantum.plugin import QiskitProcessor\n",
     "\n",
     "        # firstly perform simulate\n",
     "        print(f\"\\nTest with Qiskit Simulator\")\n",
diff --git a/examples/QCE22_tutorial/sec2_gate.ipynb b/examples/QCE22_tutorial/sec2_gate.ipynb
index 2b73c5ce..2c019bfe 100644
--- a/examples/QCE22_tutorial/sec2_gate.ipynb
+++ b/examples/QCE22_tutorial/sec2_gate.ipynb
@@ -11786,7 +11786,7 @@
     "from torchquantum.datasets import MNIST\n",
     "import torch.optim as optim\n",
     "\n",
-    "from torchquantum.plugins import tq2qiskit, qiskit2tq\n",
+    "from torchquantum.plugin import tq2qiskit, qiskit2tq\n",
     "from torchquantum.utils import (build_module_from_op_list,\n",
     "                                build_module_op_list,\n",
     "                                get_v_c_reg_mapping,\n",
@@ -12494,7 +12494,7 @@
     }
    ],
    "source": [
-    "from torchquantum.plugins import tq2qiskit\n",
+    "from torchquantum.plugin import tq2qiskit\n",
     "gene_choice = model.arch_space\n",
     "gene_len = len(gene_choice)\n",
     "n_samples=1\n",
@@ -12535,7 +12535,7 @@
    },
    "outputs": [],
    "source": [
-    "from torchquantum.plugins import QiskitProcessor\n",
+    "from torchquantum.plugin import QiskitProcessor\n",
     "from qiskit import IBMQ\n",
     "IBMQ.save_account('0238b0afc0dc515fe7987b02706791d1719cb89b68befedc125eded0607e6e9e9f26d3eed482f66fdc45fdfceca3aab2edb9519d96b39e9c78040194b86e7858', overwrite=True)\n",
     "\n",
@@ -16233,7 +16233,7 @@
     "\n",
     "from torchquantum.datasets import MNIST\n",
     "from torch.optim.lr_scheduler import CosineAnnealingLR\n",
-    "from torchquantum.plugins import tq2qiskit, qiskit2tq\n",
+    "from torchquantum.plugin import tq2qiskit, qiskit2tq\n",
     "from torchquantum.utils import (build_module_from_op_list,\n",
     "                                build_module_op_list,\n",
     "                                get_v_c_reg_mapping,\n",
@@ -16241,7 +16241,7 @@
     "                                get_p_v_reg_mapping,\n",
     "                                get_cared_configs)\n",
     "\n",
-    "from torchquantum.plugins import QiskitProcessor\n",
+    "from torchquantum.plugin import QiskitProcessor\n",
     "\n",
     "import random\n",
     "import numpy as np"
@@ -17221,7 +17221,7 @@
     }
    },
    "source": [
-    "Train and valid the model on ibmq_quito. You need to import `QiskitProcessor` from `torchquantum.plugins` to create a processor that handles your access to real quantum computer. You can set whether use real quantum computer or qiskit's noise model, and the backend of your quantum computer. Call `model.set_qiskit_processor` to attach the processor to your model."
+    "Train and valid the model on ibmq_quito. You need to import `QiskitProcessor` from `torchquantum.plugin` to create a processor that handles your access to real quantum computer. You can set whether use real quantum computer or qiskit's noise model, and the backend of your quantum computer. Call `model.set_qiskit_processor` to attach the processor to your model."
    ]
   },
   {
@@ -17363,7 +17363,7 @@
     }
    ],
    "source": [
-    "from torchquantum.plugins import QiskitProcessor\n",
+    "from torchquantum.plugin import QiskitProcessor\n",
     "model = Q2Model().to(device)\n",
     "processor_real_qc = QiskitProcessor(use_real_qc=True, backend_name='ibmq_quito')\n",
     "model.set_qiskit_processor(processor_real_qc)\n",
@@ -18134,7 +18134,7 @@
    "cell_type": "code",
    "source": [
     "from qiskit.compiler.transpiler import transpile\n",
-    "from torchquantum.plugins import tq2qiskit, qiskit2tq\n",
+    "from torchquantum.plugin import tq2qiskit, qiskit2tq\n",
     "from torch.nn.parameter import Parameter\n",
     "\n",
     "def get_weight_from_model(model):\n",
@@ -18646,7 +18646,7 @@
    "cell_type": "code",
    "source": [
     "from qiskit.compiler.transpiler import transpile\n",
-    "from torchquantum.plugins import tq2qiskit, qiskit2tq\n",
+    "from torchquantum.plugin import tq2qiskit, qiskit2tq\n",
     "from torch.nn.parameter import Parameter\n",
     "from qiskit.test.mock import FakeValencia\n",
     "import matplotlib.pyplot as plt\n",
diff --git a/examples/__init__.py b/examples/__init__.py
index e69de29b..945fa3a6 100644
--- a/examples/__init__.py
+++ b/examples/__init__.py
@@ -0,0 +1,24 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
diff --git a/examples/amplitude_encoding_mnist/mnist_example.py b/examples/amplitude_encoding_mnist/mnist_example.py
index f1f468c1..ad92bb1f 100644
--- a/examples/amplitude_encoding_mnist/mnist_example.py
+++ b/examples/amplitude_encoding_mnist/mnist_example.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
@@ -6,7 +30,7 @@
 import torchquantum as tq
 import torchquantum.functional as tqf
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 import random
diff --git a/examples/amplitude_encoding_mnist/mnist_new.py b/examples/amplitude_encoding_mnist/mnist_new.py
index db2b9759..491a1e20 100644
--- a/examples/amplitude_encoding_mnist/mnist_new.py
+++ b/examples/amplitude_encoding_mnist/mnist_new.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 """
 author: Vivek Yanamadula @Vivekyy
 """
@@ -7,8 +31,8 @@
 
 import torchquantum as tq
 
-from torchquantum.datasets import MNIST
-from torchquantum.operators import op_name_dict
+from torchquantum.dataset import MNIST
+from torchquantum.operator import op_name_dict
 from typing import List
 
 
diff --git a/examples/clifford_qnn/mnist_clifford_qnn.py b/examples/clifford_qnn/mnist_clifford_qnn.py
index 89df1086..2b7f0a95 100644
--- a/examples/clifford_qnn/mnist_clifford_qnn.py
+++ b/examples/clifford_qnn/mnist_clifford_qnn.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
@@ -5,7 +29,7 @@
 
 import torchquantum as tq
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 import random
@@ -14,7 +38,7 @@
 # need to make sure all the gates are RX RY RZ and parameters are 0, pi/2,
 # pi, 3pi/2 four types
 
-from torchquantum.layers import RXYZCXLayer0
+from torchquantum.layer import RXYZCXLayer0
 
 
 class QFCModel(tq.QuantumModule):
@@ -174,7 +198,7 @@ def main():
     # # run on Qiskit simulator and real Quantum Computers
     # try:
     #     from qiskit import IBMQ
-    #     from torchquantum.plugins import QiskitProcessor
+    #     from torchquantum.plugin import QiskitProcessor
     #
     #     # firstly perform simulate
     #     print(f"\nTest with Qiskit Simulator")
diff --git a/examples/converter_tq_qiskit/convert.py b/examples/converter_tq_qiskit/convert.py
index 3c5d2429..8551de00 100644
--- a/examples/converter_tq_qiskit/convert.py
+++ b/examples/converter_tq_qiskit/convert.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import argparse
 
@@ -72,7 +96,7 @@ def main():
 
     q_model = QLayer()
     # convert the tq module to qiskit and draw
-    from torchquantum.plugins import tq2qiskit, qiskit2tq
+    from torchquantum.plugin import tq2qiskit, qiskit2tq
 
     circ = tq2qiskit(tq.QuantumDevice(n_wires=q_model.n_wires), q_model, draw=True)
 
diff --git a/examples/cuquantum/cuquantum_plugin.py b/examples/cuquantum/cuquantum_plugin.py
new file mode 100644
index 00000000..f31665e8
--- /dev/null
+++ b/examples/cuquantum/cuquantum_plugin.py
@@ -0,0 +1,98 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from cuquantum import contract
+from cuquantum import CircuitToEinsum
+import torchquantum as tq
+from torchquantum.plugin import op_history2qiskit
+from torchquantum.measurement import expval_joint_analytical
+import cupy as cp
+
+def expval_joint_analytical_cuquantum(qdev, observable):
+    """Computes the expectation value of a joint observable using cuquantum.
+
+    Args:
+        qdev (QuantumDevice): Quantum device to compute the expectation value on.
+        observable (str): Joint observable to compute the expectation value of.
+
+    Returns:
+        float: The expectation value of the joint observable.
+    """
+    op_history = qdev.op_history
+    qiskit_circ = op_history2qiskit(qdev.n_wires, op_history)
+    myconverter = CircuitToEinsum(qiskit_circ, dtype='complex128', backend=cp)
+    expression, operands = myconverter.expectation(observable, lightcone=True)
+    expec = contract(expression, *operands)
+    return expec
+
+
+if __name__ == '__main__':
+    
+    ops = [
+        {'name': 'u3', 'wires': 0, 'trainable': True},
+        {'name': 'u3', 'wires': 1, 'trainable': True},
+        {'name': 'cx', 'wires': [0, 1]},
+        {'name': 'cx', 'wires': [1, 0]},
+        {'name': 'u3', 'wires': 0, 'trainable': True},
+        {'name': 'u3', 'wires': 1, 'trainable': True},
+        {'name': 'cx', 'wires': [0, 1]},
+        {'name': 'cx', 'wires': [1, 0]},
+    ]
+
+    qmodule = tq.QuantumModule.from_op_history(ops)
+
+    qdev = tq.QuantumDevice(n_wires=2, bsz=1, record_op=True)
+
+    qmodule(qdev)
+
+    op_history = qdev.op_history
+
+    # print(op_history)
+
+    qiskit_circ = op_history2qiskit(qdev.n_wires, op_history)
+    # print(qiskit_circ)
+
+    myconverter = CircuitToEinsum(qiskit_circ, dtype='complex128', backend=cp)
+    pauli_string = 'IX'
+    expression, operands = myconverter.expectation(pauli_string, lightcone=True)
+    expec = contract(expression, *operands)
+    print(f'expectation value for {pauli_string}: {expec}')
+
+    print(f"torchquantum expval: {expval_joint_analytical(qdev, pauli_string)}")
+    print(expval_joint_analytical_cuquantum(qdev, pauli_string))
+    
+
+    # # expectation value from reduced density matrix
+    # qubits = myconverter.qubits
+    # where = qubits[1:5]
+    # rdm_expression, rdm_operands = myconverter.reduced_density_matrix(where, lightcone=True)
+    # rdm = contract(rdm_expression, *rdm_operands)
+
+    # pauli_x = cp.asarray([[0,1],[1,0]], dtype=myconverter.dtype)
+    # pauli_z = cp.asarray([[1,0],[0,-1]], dtype=myconverter.dtype)
+    # expec_from_rdm = cp.einsum('abcdABCD,aA,bB,cC,dD->', rdm, pauli_x, pauli_x, pauli_z, pauli_z)
+
+
+    # print(f"is expectation value in agreement?", cp.allclose(expec, expec_from_rdm))
+
diff --git a/examples/encoder_examples/encoder_8x2ry.py b/examples/encoder_examples/encoder_8x2ry.py
index a9364e87..fcb731a8 100644
--- a/examples/encoder_examples/encoder_8x2ry.py
+++ b/examples/encoder_examples/encoder_8x2ry.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torchquantum as tq
 
diff --git a/examples/gradient_pruning/__init__.py b/examples/gradient_pruning/__init__.py
index e69de29b..945fa3a6 100644
--- a/examples/gradient_pruning/__init__.py
+++ b/examples/gradient_pruning/__init__.py
@@ -0,0 +1,24 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
diff --git a/examples/gradient_pruning/callbacks.py b/examples/gradient_pruning/callbacks.py
index 367b4273..cd11e5cd 100644
--- a/examples/gradient_pruning/callbacks.py
+++ b/examples/gradient_pruning/callbacks.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import copy
 import time
 from typing import List, Any, Dict
@@ -14,7 +38,7 @@
 from torchpack.utils.typing import Trainer
 from torchpack import distributed as dist
 from torchquantum.super_utils import get_named_sample_arch
-from torchquantum.utils import legalize_unitary
+from torchquantum.util import legalize_unitary
 
 
 __all__ = [
diff --git a/examples/gradient_pruning/probabilistic_gradient_pruning.ipynb b/examples/gradient_pruning/probabilistic_gradient_pruning.ipynb
index 720ca31d..bb61de81 100644
--- a/examples/gradient_pruning/probabilistic_gradient_pruning.ipynb
+++ b/examples/gradient_pruning/probabilistic_gradient_pruning.ipynb
@@ -917,7 +917,7 @@
         "  model = QMultiFCModel0(configs.model.arch)\n",
         "\n",
         "  if configs.qiskit.use_qiskit_train or configs.qiskit.use_qiskit_valid:\n",
-        "      from torchquantum.plugins import QiskitProcessor\n",
+        "      from torchquantum.plugin import QiskitProcessor\n",
         "      processor = QiskitProcessor(use_real_qc=configs.qiskit.use_real_qc, n_shots=configs.qiskit.n_shots, backend_name=configs.qiskit.backend_name)\n",
         "      model.set_qiskit_processor(processor)\n",
         "\n",
diff --git a/examples/gradient_pruning/q_models.py b/examples/gradient_pruning/q_models.py
index aae5a896..1073ac72 100644
--- a/examples/gradient_pruning/q_models.py
+++ b/examples/gradient_pruning/q_models.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 import torch
 import torch.nn.functional as F
diff --git a/examples/gradient_pruning/trainers.py b/examples/gradient_pruning/trainers.py
index 84318e84..f82bbe61 100644
--- a/examples/gradient_pruning/trainers.py
+++ b/examples/gradient_pruning/trainers.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch.nn as nn
 import torch.nn.utils.prune
 
@@ -5,7 +29,7 @@
 from torchpack.train import Trainer
 from torchpack.utils.typing import Optimizer, Scheduler
 from torchpack.utils.config import configs
-from torchquantum.utils import get_unitary_loss, build_module_op_list
+from torchquantum.util import get_unitary_loss, build_module_op_list
 from torchpack.utils.logging import logger
 from torchpack.callbacks.writers import TFEventWriter
 from torchpack.train.exception import StopTraining
diff --git a/examples/grover/README.md b/examples/grover/README.md
new file mode 100644
index 00000000..91437baa
--- /dev/null
+++ b/examples/grover/README.md
@@ -0,0 +1,8 @@
+# Grover's Search Algorithm
+
+Grover's Search Algorithm [1] is an algorithm which can speed up an unstructured search problem quadratically using amplitude amplification. A detailed walkthrough can be found [here](https://quantum-computing.ibm.com/composer/docs/iqx/guide/grovers-algorithm). The file `grover_example_sudoku.py` provides an example of how to use the algorithm to solve a sudoku puzzle of size 2x2.
+
+
+## References
+
+1. Grover, Lov K.. “A fast quantum mechanical algorithm for database search.” Symposium on the Theory of Computing (1996).
\ No newline at end of file
diff --git a/examples/grover/grover_example_sudoku.py b/examples/grover/grover_example_sudoku.py
new file mode 100644
index 00000000..25761594
--- /dev/null
+++ b/examples/grover/grover_example_sudoku.py
@@ -0,0 +1,93 @@
+""" 
+This example is based on Qiskt's Texbook: https://learn.qiskit.org/course/ch-algorithms/grovers-algorithm#sudoku
+
+We will now tackle a 2x2 binary sudoku problem using Grover's algorithm,  where we don't necessarily possess 
+prior knowledge of the solution. The problem adheres to two simple rules:
+
+1. No column can have the same value repeated.
+2. No row can have the same value repeated.
+
+We will use the following 4 variables:
+
+---------
+| a | b |
+---------
+| c | d |
+---------
+
+Please keep in mind that while utilizing Grover's algorithm to solve this particular problem may not be practical 
+(as the solution can likely be determined mentally), the intention of this example is to showcase the process of 
+transforming classical decision problems into oracles suitable for Grover's algorithm.
+
+We need to check for four conditions:
+
+1. a != b
+2. c != d
+3. a != c
+4. b != d
+"""
+
+import torchquantum as tq
+from torchquantum.algorithms import Grover
+
+
+# To simplify the process, we can compile this set of comparisons into a list of clauses for convenience.
+clauses = [ [0, 1], [0, 2], [1, 3], [2, 3] ]
+
+# This circuit checks if input0 is equal to input1 and stores the output in output. 
+# The output of each comparison is stored in a new bit.
+def XOR(input0, input1, output):
+    op1 = {'name': 'cnot', 'wires': [input0, output]}
+    op2 = {'name': 'cnot', 'wires': [input1, output]}
+    return [op1, op2]
+    
+# To verify each clause, we repeat the above circuit for every pairing in the `clauses`. 
+ops = []
+clause_qubits = [4, 5, 6, 7]
+for i, clause in enumerate(clauses):
+	ops += XOR(clause[0], clause[1], clause_qubits[i])
+
+# To determine if the assignments of a, b, c, d are a solution to the sudoku, we examine the final state 
+# of the `clause_qubits`. Only when all of these qubits are 1, it indicates that the clauses are satisfied. 
+# To achieve this, we incorporate a multi-controlled Toffoli gate in our checking circuit. This gate 
+# ensures that a single output bit will be set to 1 if and only if all the clauses are satisfied, 
+# allowing us to easily determine if our assignment is a solution.
+ops += [{'name': 'multicnot', 'n_wires': 5, 'wires': [4,5,6,7,8]}]
+
+# In order to transform our checking circuit into a Grover oracle, it is crucial to ensure that the `clause_qubits` 
+# are always returned to their initial state after the computation. This guarantees that `clause_qubits` are all 
+# set to 0 once our circuit has finished running. To achieve this, we include a step called "uncomputation" 
+# where we repeat the segment of the circuit that computes the clauses. This uncomputation step ensures the 
+# desired state restoration, enabling us to effectively use the circuit as a Grover oracle.
+for qubit, clause in enumerate(clauses):
+	ops += XOR(clause[0], clause[1], qubit + 4)
+
+# Full Algorithm
+# We can combine all the components we have discussed so far
+
+qmodule = tq.QuantumModule.from_op_history(ops)
+iterations = 2
+qdev = tq.QuantumDevice(n_wires=9, device="cpu")
+
+# Initialize output qubit (last qubit) in state |->
+qdev.x(wires=8)
+qdev.h(wires=8)
+
+# Perform Grover's Search
+grover = Grover(qmodule, iterations, 4)
+result = grover.execute(qdev)
+bitstring = result.bitstring[0]
+
+# Extract the top two most likely solutions
+res = {k: v for k, v in sorted(bitstring.items(), key=lambda item: item[1], reverse=True)}
+
+# Print the top two most likely solutions
+top_keys = list(res.keys())[:2]
+print("Top two most likely solutions:")
+for key in top_keys:
+	print("Solution: ", key)
+	print("a = ", key[0])
+	print("b = ", key[1])
+	print("c = ", key[2])
+	print("d = ", key[3])
+	print("")
\ No newline at end of file
diff --git a/examples/hadamard_grad/circ.py b/examples/hadamard_grad/circ.py
new file mode 100644
index 00000000..6b9129fe
--- /dev/null
+++ b/examples/hadamard_grad/circ.py
@@ -0,0 +1,107 @@
+import torchquantum as tq
+
+op_types=(
+    tq.Hadamard,
+    tq.SHadamard,
+    tq.PauliX,
+    tq.PauliY,
+    tq.PauliZ,
+    tq.S,
+    tq.T,
+    tq.SX,
+    tq.CNOT,
+)
+
+class Circ1(tq.QuantumModule):
+    def __init__(self):
+        super().__init__()
+        self.n_wires = 4
+        self.gate1 = tq.operator.OpPauliExp(coeffs=[1.0], paulis=["YXIX"], theta=0.5, trainable=True)
+
+    def forward(self):
+        qdev = tq.QuantumDevice(
+            n_wires=self.n_wires, bsz=1, device='cpu', record_op=True
+        )
+        self.gate1(qdev, wires=[0, 1, 2, 3])
+        expval = tq.measurement.expval_joint_analytical(qdev, observable="ZZZZ")
+
+        return expval, qdev
+
+class Circ2(tq.QuantumModule):
+    def __init__(self):
+        super().__init__()
+        self.n_wires = 4
+        self.gate1 = tq.operator.OpPauliExp(coeffs=[1.0, 0.5], paulis=["YXIX", "ZIXZ"], theta=0.5, trainable=True)
+
+    def forward(self):
+        qdev = tq.QuantumDevice(
+            n_wires=self.n_wires, bsz=1, device='cpu', record_op=True
+        )
+        self.gate1(qdev, wires=[0, 1, 2, 3])
+        expval = tq.measurement.expval_joint_analytical(qdev, observable="ZZZZ")
+
+        return expval, qdev
+
+class Circ3(tq.QuantumModule):
+    def __init__(self):
+        super().__init__()
+        self.n_wires = 4
+        self.gate1 = tq.operator.OpPauliExp(coeffs=[1.0], paulis=["XIII"], theta=0.5, trainable=True) # Note this is RX gate
+        self.gate2 = tq.operator.OpPauliExp(coeffs=[0.722], paulis=["YXIX"], theta=0.5, trainable=True)
+        self.gate3 = tq.operator.OpPauliExp(coeffs=[1.0, 0.5], paulis=["YXIX", "ZIXZ"], theta=0.2, trainable=True)
+        self.gate4 = tq.operator.OpPauliExp(coeffs=[1.0], paulis=["YYYY"], theta=0.5, trainable=True)
+
+        self.random_layer1 = tq.RandomLayer(op_types=op_types, n_ops=50, wires=list(range(self.n_wires)))
+        self.random_layer2 = tq.RandomLayer(op_types=op_types, n_ops=50, wires=list(range(self.n_wires)))
+        self.random_layer3 = tq.RandomLayer(op_types=op_types, n_ops=50, wires=list(range(self.n_wires)))
+        self.random_layer4 = tq.RandomLayer(op_types=op_types, n_ops=50, wires=list(range(self.n_wires)))
+        self.random_layer5 = tq.RandomLayer(op_types=op_types, n_ops=50, wires=list(range(self.n_wires)))
+
+
+    def forward(self):
+        qdev = tq.QuantumDevice(
+            n_wires=self.n_wires, bsz=1, device='cpu', record_op=True
+        )
+
+        qdev.h(wires=1)
+        qdev.h(wires=3)
+        qdev.cnot(wires=[1, 0])
+        qdev.cnot(wires=[3, 2])
+
+        self.random_layer1(qdev)
+        self.gate1(qdev, wires=[0, 1, 2, 3])
+        self.random_layer2(qdev)
+        self.gate2(qdev, wires=[0, 1, 2, 3])
+        self.random_layer3(qdev)
+        self.gate3(qdev, wires=[0, 1, 2, 3])
+        self.random_layer4(qdev)
+        self.gate4(qdev, wires=[0, 1, 2, 3])
+        self.random_layer5(qdev)
+
+        expval = tq.measurement.expval_joint_analytical(qdev, observable="ZZZZ")
+
+        return expval, qdev
+
+
+if __name__ == '__main__':
+
+    circ1 = Circ1()
+    expval1, qdev1 = circ1()
+    print('expval:')
+    print(expval1)
+    print('op_history:')
+    print(qdev1.op_history)
+
+    circ2 = Circ2()
+    expval2, qdev2 = circ2()
+    print('expval:')
+    print(expval2)
+    print('op_history:')
+    print(qdev2.op_history)
+
+    circ3 = Circ3()
+    expval3, qdev3 = circ3()
+    print('expval:')
+    print(expval3)
+    print('op_history:')
+    print(qdev3.op_history)
diff --git a/examples/hadamard_grad/example.ipynb b/examples/hadamard_grad/example.ipynb
new file mode 100644
index 00000000..df880574
--- /dev/null
+++ b/examples/hadamard_grad/example.ipynb
@@ -0,0 +1,144 @@
+{
+ "cells": [
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "# Tutorial on Hadamard Test Based Gradient Estimation"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Set Up\n",
+    "\n",
+    "We define three types of example circuits in ./circ.py and here we use Circ1 as an example"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 1,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "from hadamard_grad import hadamard_grad\n",
+    "from circ import Circ1"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Run Circuit\n",
+    "\n",
+    "We need to run the circuit first to record its operations in the q_device"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "expval:\n",
+      "tensor([0.8776], grad_fn=<SelectBackward0>)\n",
+      "op_history:\n",
+      "[{'name': 'OpPauliExp', 'wires': [0, 1, 2, 3], 'coeffs': [1.0], 'paulis': ['YXIX'], 'inverse': False, 'trainable': True, 'params': 0.5}]\n"
+     ]
+    }
+   ],
+   "source": [
+    "circ1 = Circ1()\n",
+    "expval1, qdev1 = circ1()\n",
+    "print('expval:')\n",
+    "print(expval1)\n",
+    "print('op_history:')\n",
+    "print(qdev1.op_history)"
+   ]
+  },
+  {
+   "cell_type": "markdown",
+   "metadata": {},
+   "source": [
+    "## Gradient Estimation\n",
+    "\n",
+    "To facilitate torchquantum v0.1.7, we need to manually extrac the following three information from the q_device and circuit:\n",
+    "\n",
+    "- op_history: The history of quantum operations applied on the q_device.\n",
+    "- n_wires: The number of wires (quantum bits) in the q_device.\n",
+    "- observable: The observable of the original circuit, for which the gradients are computed."
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 3,
+   "metadata": {},
+   "outputs": [],
+   "source": [
+    "op_history = qdev1.op_history\n",
+    "n_wires = qdev1.n_wires\n",
+    "observable = 'ZZZZ'"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 4,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "/vast/palmer/home.grace/dl2276/AllProjects/torchquantum/torchquantum/functional/func_controlled_unitary.py:99: UserWarning: To copy construct from a tensor, it is recommended to use sourceTensor.clone().detach() or sourceTensor.clone().detach().requires_grad_(True), rather than torch.tensor(sourceTensor).\n",
+      "  unitary = torch.tensor(torch.zeros(2**n_wires, 2**n_wires, dtype=C_DTYPE))\n"
+     ]
+    },
+    {
+     "data": {
+      "text/plain": [
+       "[tensor(-0.4794)]"
+      ]
+     },
+     "execution_count": 4,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "hadamard_grad(op_history, n_wires, observable)\n",
+    "# -0.47942554"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3.10.11 ('tq')",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.10.11"
+  },
+  "orig_nbformat": 4,
+  "vscode": {
+   "interpreter": {
+    "hash": "0e29a0e2839e50afa2f3a774fbdc59fa5f031cf090cdc0c9e6a9a24240713eb0"
+   }
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/examples/hadamard_grad/hadamard_grad.py b/examples/hadamard_grad/hadamard_grad.py
new file mode 100644
index 00000000..76a98354
--- /dev/null
+++ b/examples/hadamard_grad/hadamard_grad.py
@@ -0,0 +1,84 @@
+import torch
+import torchquantum as tq
+from torchquantum.measurement import expval_joint_analytical
+
+def gradient_circuit(left, target, right, n_wires, observable):
+    '''
+    Compute the gradient for the target gate.
+
+    Parameters:
+    - left: The gates to the left of the target gate.
+    - target: The target gate for which the gradient is computed.
+    - right: The gates to the right of the target gate.
+    - n_wires: The number of wires (quantum bits) in the circuit.
+    - observable: The observable of the original circuit, for which the gradients are computed.
+
+    Returns:
+    - The computed gradient for the target gate, analytical
+    '''
+    ancilla_qubit = n_wires
+
+    gradient = 0
+    for coeff, pauli in zip(target['coeffs'], target['paulis']):
+
+        dev = tq.QuantumDevice(n_wires=n_wires+1, bsz=1, device="cpu") # use device='cuda' for GPU
+        # ancilla
+        dev.h(wires=ancilla_qubit)
+        # left
+        for op_info in left:
+            if 'coeffs' in op_info:
+                # Evolution
+                op = tq.operator.OpPauliExp(coeffs=op_info['coeffs'], paulis=op_info['paulis'], theta=op_info['params'], trainable=False)
+                op(dev, wires=op_info['wires'])
+            else:
+                # other gates
+                op = tq.QuantumModule.from_op_history([op_info])
+                op(dev)
+        # target
+        generator = tq.algorithm.Hamiltonian(coeffs=[1.0], paulis=[pauli]) # ZZZZ
+        dev.controlled_unitary(params=generator.matrix, c_wires=[ancilla_qubit], t_wires=target['wires'])
+        # ancilla
+        dev.h(wires=ancilla_qubit)
+        # right
+        for op_info in right:
+            if 'coeffs' in op_info:
+                # Evolution
+                op = tq.operator.OpPauliExp(coeffs=op_info['coeffs'], paulis=op_info['paulis'], theta=op_info['params'], trainable=False)
+                op(dev, wires=op_info['wires'])
+            else:
+                # other gates
+                op = tq.QuantumModule.from_op_history([op_info])
+                op(dev)
+
+        # measurement
+        original_measurement = observable # 'ZZZZ'
+        expval = expval_joint_analytical(dev, original_measurement+'Y')
+        gradient -= coeff * torch.mean(expval)
+
+    return gradient
+
+def hadamard_grad(op_history, n_wires, observable):
+    '''
+    Return the gradients for parameters in the q_device.
+
+    Parameters:
+    - op_history: The history of quantum operations applied on the q_device.
+    - n_wires: The number of wires (quantum bits) in the q_device.
+    - observable: The observable of the original circuit, for which the gradients are computed.
+
+    Returns:
+    - A list of gradients, ordered as the list the operations in op_history
+    '''
+    gradient_list = []
+    for i, op in enumerate(op_history):
+        if not op['trainable']:
+            gradient_list.append(None)
+        else:
+            left = op_history[:i+1]
+            target = op
+            right = op_history[i+1:]
+            gradient_list.append(
+                gradient_circuit(left, target, right, n_wires, observable)
+            )
+
+    return gradient_list
\ No newline at end of file
diff --git a/examples/index.rst b/examples/index.rst
index 2f5fc51b..e36da434 100644
--- a/examples/index.rst
+++ b/examples/index.rst
@@ -8,3 +8,4 @@ TorchQuantum Examples
    param_shift_onchip_training/param_shift_onchip_training.ipynb
    quantum_kernel_method/quantum_kernel_method.ipynb
    quanvolution/quanvolution.ipynb
+   superdense_coding/superdense_coding_torchquantum.ipynb
\ No newline at end of file
diff --git a/examples/simple_mnist/README.md b/examples/mnist/README.md
similarity index 100%
rename from examples/simple_mnist/README.md
rename to examples/mnist/README.md
diff --git a/examples/mnist/mnist.py b/examples/mnist/mnist.py
new file mode 100644
index 00000000..65276e91
--- /dev/null
+++ b/examples/mnist/mnist.py
@@ -0,0 +1,281 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torch.nn.functional as F
+import torch.optim as optim
+import argparse
+import random
+import numpy as np
+
+import torchquantum as tq
+from torchquantum.plugin import (
+    tq2qiskit_measurement,
+    qiskit_assemble_circs,
+    op_history2qiskit,
+    op_history2qiskit_expand_params,
+)
+
+from torchquantum.dataset import MNIST
+from torch.optim.lr_scheduler import CosineAnnealingLR
+
+
+class QFCModel(tq.QuantumModule):
+    class QLayer(tq.QuantumModule):
+        def __init__(self):
+            super().__init__()
+            self.n_wires = 4
+            self.random_layer = tq.RandomLayer(
+                n_ops=50, wires=list(range(self.n_wires))
+            )
+
+            # gates with trainable parameters
+            self.rx0 = tq.RX(has_params=True, trainable=True)
+            self.ry0 = tq.RY(has_params=True, trainable=True)
+            self.rz0 = tq.RZ(has_params=True, trainable=True)
+            self.crx0 = tq.CRX(has_params=True, trainable=True)
+
+        def forward(self, qdev: tq.QuantumDevice):
+            self.random_layer(qdev)
+
+            # some trainable gates (instantiated ahead of time)
+            self.rx0(qdev, wires=0)
+            self.ry0(qdev, wires=1)
+            self.rz0(qdev, wires=3)
+            self.crx0(qdev, wires=[0, 2])
+
+            # add some more non-parameterized gates (add on-the-fly)
+            qdev.h(wires=3)  # type: ignore
+            qdev.sx(wires=2)  # type: ignore
+            qdev.cnot(wires=[3, 0])  # type: ignore
+            qdev.rx(
+                wires=1,
+                params=torch.tensor([0.1]),
+                static=self.static_mode,
+                parent_graph=self.graph,
+            )  # type: ignore
+
+    def __init__(self):
+        super().__init__()
+        self.n_wires = 4
+        self.encoder = tq.GeneralEncoder(tq.encoder_op_list_name_dict["4x4_u3rx"])
+
+        self.q_layer = self.QLayer()
+        self.measure = tq.MeasureAll(tq.PauliZ)
+
+    def forward(self, x, use_qiskit=False):
+        qdev = tq.QuantumDevice(
+            n_wires=self.n_wires, bsz=x.shape[0], device=x.device, record_op=True
+        )
+
+        bsz = x.shape[0]
+        x = F.avg_pool2d(x, 6).view(bsz, 16)
+        devi = x.device
+
+        if use_qiskit:
+            # use qiskit to process the circuit
+            # create the qiskit circuit for encoder
+            self.encoder(qdev, x)  
+            op_history_parameterized = qdev.op_history
+            qdev.reset_op_history()
+            encoder_circs = op_history2qiskit_expand_params(self.n_wires, op_history_parameterized, bsz=bsz)
+
+            # create the qiskit circuit for trainable quantum layers
+            self.q_layer(qdev)
+            op_history_fixed = qdev.op_history
+            qdev.reset_op_history()
+            q_layer_circ = op_history2qiskit(self.n_wires, op_history_fixed)
+
+            # create the qiskit circuit for measurement
+            measurement_circ = tq2qiskit_measurement(qdev, self.measure)
+
+            # assemble the encoder, trainable quantum layers, and measurement circuits
+            assembled_circs = qiskit_assemble_circs(
+                encoder_circs, q_layer_circ, measurement_circ
+            )
+
+            # call the qiskit processor to process the circuit
+            x0 = self.qiskit_processor.process_ready_circs(qdev, assembled_circs).to(  # type: ignore
+                devi
+            )
+            x = x0
+
+        else:
+            # use torchquantum to process the circuit
+            self.encoder(qdev, x)
+            qdev.reset_op_history()
+            self.q_layer(qdev)
+            x = self.measure(qdev)
+
+        x = x.reshape(bsz, 2, 2).sum(-1).squeeze()
+        x = F.log_softmax(x, dim=1)
+
+        return x
+
+
+def train(dataflow, model, device, optimizer):
+    for feed_dict in dataflow["train"]:
+        inputs = feed_dict["image"].to(device)
+        targets = feed_dict["digit"].to(device)
+
+        outputs = model(inputs)
+        loss = F.nll_loss(outputs, targets)
+        optimizer.zero_grad()
+        loss.backward()
+        optimizer.step()
+        print(f"loss: {loss.item()}", end="\r")
+
+
+def valid_test(dataflow, split, model, device, qiskit=False):
+    target_all = []
+    output_all = []
+    with torch.no_grad():
+        for feed_dict in dataflow[split]:
+            inputs = feed_dict["image"].to(device)
+            targets = feed_dict["digit"].to(device)
+
+            outputs = model(inputs, use_qiskit=qiskit)
+
+            target_all.append(targets)
+            output_all.append(outputs)
+        target_all = torch.cat(target_all, dim=0)
+        output_all = torch.cat(output_all, dim=0)
+
+    _, indices = output_all.topk(1, dim=1)
+    masks = indices.eq(target_all.view(-1, 1).expand_as(indices))
+    size = target_all.shape[0]
+    corrects = masks.sum().item()
+    accuracy = corrects / size
+    loss = F.nll_loss(output_all, target_all).item()
+
+    print(f"{split} set accuracy: {accuracy}")
+    print(f"{split} set loss: {loss}")
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        "--static", action="store_true", help="compute with " "static mode"
+    )
+    parser.add_argument("--pdb", action="store_true", help="debug with pdb")
+    parser.add_argument(
+        "--wires-per-block", type=int, default=2, help="wires per block int static mode"
+    )
+    parser.add_argument(
+        "--epochs", type=int, default=2, help="number of training epochs"
+    )
+
+    args = parser.parse_args()
+
+    if args.pdb:
+        import pdb
+
+        pdb.set_trace()
+
+    seed = 0
+    random.seed(seed)
+    np.random.seed(seed)
+    torch.manual_seed(seed)
+
+    dataset = MNIST(
+        root="./mnist_data",
+        train_valid_split_ratio=[0.9, 0.1],
+        digits_of_interest=[3, 6],
+        n_test_samples=75,
+    )
+    dataflow = dict()
+
+    for split in dataset:
+        sampler = torch.utils.data.RandomSampler(dataset[split])
+        dataflow[split] = torch.utils.data.DataLoader(
+            dataset[split],
+            batch_size=256,
+            sampler=sampler,
+            num_workers=8,
+            pin_memory=True,
+        )
+
+    use_cuda = torch.cuda.is_available()
+    device = torch.device("cuda" if use_cuda else "cpu")
+
+    model = QFCModel().to(device)
+
+    n_epochs = args.epochs
+    optimizer = optim.Adam(model.parameters(), lr=5e-3, weight_decay=1e-4)
+    scheduler = CosineAnnealingLR(optimizer, T_max=n_epochs)
+
+    if args.static:
+        # optionally to switch to the static mode, which can bring speedup
+        # on training
+        model.q_layer.static_on(wires_per_block=args.wires_per_block)
+
+    for epoch in range(1, n_epochs + 1):
+        # train
+        print(f"Epoch {epoch}:")
+        train(dataflow, model, device, optimizer)
+        print(optimizer.param_groups[0]["lr"])
+
+        # valid
+        valid_test(dataflow, "valid", model, device)
+        scheduler.step()
+
+    # test
+    valid_test(dataflow, "test", model, device, qiskit=False)
+
+    # run on Qiskit simulator and real Quantum Computers
+    try:
+        from qiskit import IBMQ
+        from torchquantum.plugin import QiskitProcessor
+
+        # firstly perform simulate
+        print(f"\nTest with Qiskit Simulator")
+        processor_simulation = QiskitProcessor(use_real_qc=False)
+        model.set_qiskit_processor(processor_simulation)
+        valid_test(dataflow, "test", model, device, qiskit=True)
+
+        # then try to run on REAL QC
+        backend_name = "ibmq_lima"
+        print(f"\nTest on Real Quantum Computer {backend_name}")
+        # Please specify your own hub group and project if you have the
+        # IBMQ premium plan to access more machines.
+        processor_real_qc = QiskitProcessor(
+            use_real_qc=True,
+            backend_name=backend_name,
+            hub="ibm-q",
+            group="open",
+            project="main",
+        )
+        model.set_qiskit_processor(processor_real_qc)
+        valid_test(dataflow, "test", model, device, qiskit=True)
+    except ImportError:
+        print(
+            "Please install qiskit, create an IBM Q Experience Account and "
+            "save the account token according to the instruction at "
+            "'https://github.com/Qiskit/qiskit-ibmq-provider', "
+            "then try again."
+        )
+
+
+if __name__ == "__main__":
+    main()
diff --git a/examples/mnist/mnist_2qubit_4class.py b/examples/mnist/mnist_2qubit_4class.py
new file mode 100644
index 00000000..21a7519b
--- /dev/null
+++ b/examples/mnist/mnist_2qubit_4class.py
@@ -0,0 +1,213 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+"""
+use 2 qubit to perform 4 class classification,
+We can choose four different observables to measure the qubit state:
+    1. XX
+    2. YY
+    3. ZZ
+    4. XY
+"""
+
+import torch
+import torch.nn.functional as F
+import torch.optim as optim
+import argparse
+
+import torchquantum as tq
+import torchquantum.functional as tqf
+
+from torchquantum.measurement import expval_joint_analytical
+
+from torchquantum.dataset import MNIST
+from torch.optim.lr_scheduler import CosineAnnealingLR
+
+import random
+import numpy as np
+
+
+class QFCModel(tq.QuantumModule):
+    class QLayer(tq.QuantumModule):
+        def __init__(self):
+            super().__init__()
+            self.n_wires = 2
+            self.random_layer = tq.RandomLayer(
+                n_ops=50, wires=list(range(self.n_wires))
+            )
+
+            # gates with trainable parameters
+            self.rx0 = tq.RX(has_params=True, trainable=True)
+            self.ry0 = tq.RY(has_params=True, trainable=True)
+            self.rz0 = tq.RZ(has_params=True, trainable=True)
+            self.crx0 = tq.CRX(has_params=True, trainable=True)
+
+        def forward(self, qdev: tq.QuantumDevice):
+            self.random_layer(qdev)
+
+            # some trainable gates (instantiated ahead of time)
+            self.rx0(qdev, wires=0)
+            self.ry0(qdev, wires=1)
+            self.rz0(qdev, wires=0)
+            self.crx0(qdev, wires=[0, 1])
+
+    def __init__(self):
+        super().__init__()
+        self.n_wires = 2
+        # the encoder here is just for illustration purpose, may not be the best choice
+        self.encoder = tq.GeneralEncoder(
+            tq.encoder_op_list_name_dict["2x8_rxryrzrxryrzrxry"]
+        )
+
+        self.q_layer = self.QLayer()
+
+    def forward(self, x, use_qiskit=False):
+        qdev = tq.QuantumDevice(
+            n_wires=self.n_wires, bsz=x.shape[0], device=x.device, record_op=True
+        )
+
+        bsz = x.shape[0]
+        x = F.avg_pool2d(x, 6).view(bsz, 16)
+
+        self.encoder(qdev, x)
+        self.q_layer(qdev)
+        obs_xx = expval_joint_analytical(qdev, "XX")
+        obs_yy = expval_joint_analytical(qdev, "YY")
+        obs_zz = expval_joint_analytical(qdev, "ZZ")
+        obs_xy = expval_joint_analytical(qdev, "XY")
+
+        x = torch.stack([obs_xx, obs_yy, obs_zz, obs_xy], dim=1)
+        x = F.log_softmax(x, dim=1)
+
+        return x
+
+
+def train(dataflow, model, device, optimizer):
+    for feed_dict in dataflow["train"]:
+        inputs = feed_dict["image"].to(device)
+        targets = feed_dict["digit"].to(device)
+
+        outputs = model(inputs)
+        loss = F.nll_loss(outputs, targets)
+        optimizer.zero_grad()
+        loss.backward()
+        optimizer.step()
+        print(f"loss: {loss.item()}", end="\r")
+
+
+def valid_test(dataflow, split, model, device, qiskit=False):
+    target_all = []
+    output_all = []
+    with torch.no_grad():
+        for feed_dict in dataflow[split]:
+            inputs = feed_dict["image"].to(device)
+            targets = feed_dict["digit"].to(device)
+
+            outputs = model(inputs, use_qiskit=qiskit)
+
+            target_all.append(targets)
+            output_all.append(outputs)
+        target_all = torch.cat(target_all, dim=0)
+        output_all = torch.cat(output_all, dim=0)
+
+    _, indices = output_all.topk(1, dim=1)
+    masks = indices.eq(target_all.view(-1, 1).expand_as(indices))
+    size = target_all.shape[0]
+    corrects = masks.sum().item()
+    accuracy = corrects / size
+    loss = F.nll_loss(output_all, target_all).item()
+
+    print(f"{split} set accuracy: {accuracy}")
+    print(f"{split} set loss: {loss}")
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        "--static", action="store_true", help="compute with " "static mode"
+    )
+    parser.add_argument("--pdb", action="store_true", help="debug with pdb")
+    parser.add_argument(
+        "--wires-per-block", type=int, default=2, help="wires per block int static mode"
+    )
+    parser.add_argument(
+        "--epochs", type=int, default=5, help="number of training epochs"
+    )
+
+    args = parser.parse_args()
+
+    if args.pdb:
+        import pdb
+
+        pdb.set_trace()
+
+    seed = 0
+    random.seed(seed)
+    np.random.seed(seed)
+    torch.manual_seed(seed)
+
+    dataset = MNIST(
+        root="./mnist_data",
+        train_valid_split_ratio=[0.9, 0.1],
+        digits_of_interest=[0, 1, 2, 3],
+        n_test_samples=100,
+    )
+
+    dataflow = dict()
+
+    for split in dataset:
+        sampler = torch.utils.data.RandomSampler(dataset[split])
+        dataflow[split] = torch.utils.data.DataLoader(
+            dataset[split],
+            batch_size=256,
+            sampler=sampler,
+            num_workers=8,
+            pin_memory=True,
+        )
+
+    use_cuda = torch.cuda.is_available()
+    device = torch.device("cuda" if use_cuda else "cpu")
+
+    model = QFCModel().to(device)
+
+    n_epochs = args.epochs
+    optimizer = optim.Adam(model.parameters(), lr=5e-3, weight_decay=1e-4)
+    scheduler = CosineAnnealingLR(optimizer, T_max=n_epochs)
+
+    for epoch in range(1, n_epochs + 1):
+        # train
+        print(f"Epoch {epoch}:")
+        train(dataflow, model, device, optimizer)
+        print(optimizer.param_groups[0]["lr"])
+
+        # valid
+        valid_test(dataflow, "valid", model, device)
+        scheduler.step()
+
+    # test
+    valid_test(dataflow, "test", model, device, qiskit=False)
+
+
+if __name__ == "__main__":
+    main()
diff --git a/examples/mnist/other_implementations/mnist_example_no_binding.py b/examples/mnist/other_implementations/mnist_example_no_binding.py
new file mode 100644
index 00000000..1ac849ff
--- /dev/null
+++ b/examples/mnist/other_implementations/mnist_example_no_binding.py
@@ -0,0 +1,291 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torch.nn.functional as F
+import torch.optim as optim
+import argparse
+
+import torchquantum as tq
+import torchquantum.functional as tqf
+
+from torchquantum.plugin import (
+    tq2qiskit_expand_params,
+    tq2qiskit,
+    tq2qiskit_measurement,
+    qiskit_assemble_circs,
+)
+
+from torchquantum.dataset import MNIST
+from torch.optim.lr_scheduler import CosineAnnealingLR
+
+import random
+import numpy as np
+
+
+class QFCModel(tq.QuantumModule):
+    class QLayer(tq.QuantumModule):
+        def __init__(self):
+            super().__init__()
+            self.n_wires = 4
+            self.random_layer = tq.RandomLayer(
+                n_ops=50, wires=list(range(self.n_wires))
+            )
+
+            # gates with trainable parameters
+            self.rx0 = tq.RX(has_params=True, trainable=True)
+            self.ry0 = tq.RY(has_params=True, trainable=True)
+            self.rz0 = tq.RZ(has_params=True, trainable=True)
+            self.crx0 = tq.CRX(has_params=True, trainable=True)
+
+        @tq.static_support
+        def forward(self, q_device: tq.QuantumDevice):
+            """
+            1. To convert tq QuantumModule to qiskit or run in the static
+            model, need to:
+                (1) add @tq.static_support before the forward
+                (2) make sure to add
+                    static=self.static_mode and
+                    parent_graph=self.graph
+                    to all the tqf functions, such as tqf.hadamard below
+            """
+            self.q_device = q_device
+
+            self.random_layer(self.q_device)
+
+            # some trainable gates (instantiated ahead of time)
+            self.rx0(self.q_device, wires=0)
+            self.ry0(self.q_device, wires=1)
+            self.rz0(self.q_device, wires=3)
+            self.crx0(self.q_device, wires=[0, 2])
+
+            # add some more non-parameterized gates (add on-the-fly)
+            tqf.hadamard(
+                self.q_device, wires=3, static=self.static_mode, parent_graph=self.graph
+            )
+            tqf.sx(
+                self.q_device, wires=2, static=self.static_mode, parent_graph=self.graph
+            )
+            tqf.cnot(
+                self.q_device,
+                wires=[3, 0],
+                static=self.static_mode,
+                parent_graph=self.graph,
+            )
+            tqf.rx(
+                self.q_device,
+                wires=1,
+                params=torch.tensor([0.1]),
+                static=self.static_mode,
+                parent_graph=self.graph,
+            )
+
+    def __init__(self):
+        super().__init__()
+        self.n_wires = 4
+        self.q_device = tq.QuantumDevice(n_wires=self.n_wires)
+        self.encoder = tq.GeneralEncoder(tq.encoder_op_list_name_dict["4x4_ryzxy"])
+
+        self.q_layer = self.QLayer()
+        self.measure = tq.MeasureAll(tq.PauliZ)
+
+    def forward(self, x, use_qiskit=False):
+        self.q_device.reset_states(x.shape[0])
+        bsz = x.shape[0]
+        x = F.avg_pool2d(x, 6).view(bsz, 16)
+        devi = x.device
+
+        if use_qiskit:
+            encoder_circs = tq2qiskit_expand_params(
+                self.q_device, x, self.encoder.func_list
+            )
+            q_layer_circ = tq2qiskit(self.q_device, self.q_layer)
+            measurement_circ = tq2qiskit_measurement(self.q_device, self.measure)
+            assembled_circs = qiskit_assemble_circs(
+                encoder_circs, q_layer_circ, measurement_circ
+            )
+            x0 = self.qiskit_processor.process_ready_circs(
+                self.q_device, assembled_circs
+            ).to(devi)
+            # x1 = self.qiskit_processor.process_parameterized(
+            #     self.q_device, self.encoder, self.q_layer, self.measure, x)
+            # print((x0-x1).max())
+            x = x0
+
+        else:
+            self.encoder(self.q_device, x)
+            self.q_layer(self.q_device)
+            x = self.measure(self.q_device)
+
+        x = x.reshape(bsz, 2, 2).sum(-1).squeeze()
+        x = F.log_softmax(x, dim=1)
+
+        return x
+
+
+def train(dataflow, model, device, optimizer):
+    for feed_dict in dataflow["train"]:
+        inputs = feed_dict["image"].to(device)
+        targets = feed_dict["digit"].to(device)
+
+        outputs = model(inputs)
+        loss = F.nll_loss(outputs, targets)
+        optimizer.zero_grad()
+        loss.backward()
+        optimizer.step()
+        print(f"loss: {loss.item()}", end="\r")
+
+
+def valid_test(dataflow, split, model, device, qiskit=False):
+    target_all = []
+    output_all = []
+    with torch.no_grad():
+        for feed_dict in dataflow[split]:
+            inputs = feed_dict["image"].to(device)
+            targets = feed_dict["digit"].to(device)
+
+            outputs = model(inputs, use_qiskit=qiskit)
+
+            target_all.append(targets)
+            output_all.append(outputs)
+        target_all = torch.cat(target_all, dim=0)
+        output_all = torch.cat(output_all, dim=0)
+
+    _, indices = output_all.topk(1, dim=1)
+    masks = indices.eq(target_all.view(-1, 1).expand_as(indices))
+    size = target_all.shape[0]
+    corrects = masks.sum().item()
+    accuracy = corrects / size
+    loss = F.nll_loss(output_all, target_all).item()
+
+    print(f"{split} set accuracy: {accuracy}")
+    print(f"{split} set loss: {loss}")
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        "--static", action="store_true", help="compute with " "static mode"
+    )
+    parser.add_argument("--pdb", action="store_true", help="debug with pdb")
+    parser.add_argument(
+        "--wires-per-block", type=int, default=2, help="wires per block int static mode"
+    )
+    parser.add_argument(
+        "--epochs", type=int, default=5, help="number of training epochs"
+    )
+
+    args = parser.parse_args()
+
+    if args.pdb:
+        import pdb
+
+        pdb.set_trace()
+
+    seed = 0
+    random.seed(seed)
+    np.random.seed(seed)
+    torch.manual_seed(seed)
+
+    dataset = MNIST(
+        root="./mnist_data",
+        train_valid_split_ratio=[0.9, 0.1],
+        digits_of_interest=[3, 6],
+        n_test_samples=75,
+    )
+    dataflow = dict()
+
+    for split in dataset:
+        sampler = torch.utils.data.RandomSampler(dataset[split])
+        dataflow[split] = torch.utils.data.DataLoader(
+            dataset[split],
+            batch_size=256,
+            sampler=sampler,
+            num_workers=8,
+            pin_memory=True,
+        )
+
+    use_cuda = torch.cuda.is_available()
+    device = torch.device("cuda" if use_cuda else "cpu")
+
+    model = QFCModel().to(device)
+
+    n_epochs = args.epochs
+    optimizer = optim.Adam(model.parameters(), lr=5e-3, weight_decay=1e-4)
+    scheduler = CosineAnnealingLR(optimizer, T_max=n_epochs)
+
+    if args.static:
+        # optionally to switch to the static mode, which can bring speedup
+        # on training
+        model.q_layer.static_on(wires_per_block=args.wires_per_block)
+
+    for epoch in range(1, n_epochs + 1):
+        # train
+        print(f"Epoch {epoch}:")
+        train(dataflow, model, device, optimizer)
+        print(optimizer.param_groups[0]["lr"])
+
+        # valid
+        valid_test(dataflow, "valid", model, device)
+        scheduler.step()
+
+    # test
+    valid_test(dataflow, "test", model, device, qiskit=False)
+
+    # run on Qiskit simulator and real Quantum Computers
+    try:
+        from qiskit import IBMQ
+        from torchquantum.plugin import QiskitProcessor
+
+        # firstly perform simulate
+        print(f"\nTest with Qiskit Simulator")
+        processor_simulation = QiskitProcessor(use_real_qc=False)
+        model.set_qiskit_processor(processor_simulation)
+        valid_test(dataflow, "test", model, device, qiskit=True)
+
+        # then try to run on REAL QC
+        backend_name = "ibmq_lima"
+        print(f"\nTest on Real Quantum Computer {backend_name}")
+        # Please specify your own hub group and project if you have the
+        # IBMQ premium plan to access more machines.
+        processor_real_qc = QiskitProcessor(
+            use_real_qc=True,
+            backend_name=backend_name,
+            hub="ibm-q",
+            group="open",
+            project="main",
+        )
+        model.set_qiskit_processor(processor_real_qc)
+        valid_test(dataflow, "test", model, device, qiskit=True)
+    except ImportError:
+        print(
+            "Please install qiskit, create an IBM Q Experience Account and "
+            "save the account token according to the instruction at "
+            "'https://github.com/Qiskit/qiskit-ibmq-provider', "
+            "then try again."
+        )
+
+
+if __name__ == "__main__":
+    main()
diff --git a/examples/mnist/other_implementations/mnist_example_with_binding.py b/examples/mnist/other_implementations/mnist_example_with_binding.py
new file mode 100644
index 00000000..6b779c43
--- /dev/null
+++ b/examples/mnist/other_implementations/mnist_example_with_binding.py
@@ -0,0 +1,270 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torch.nn.functional as F
+import torch.optim as optim
+import argparse
+
+import torchquantum as tq
+import torchquantum.functional as tqf
+
+from torchquantum.dataset import MNIST
+from torch.optim.lr_scheduler import CosineAnnealingLR
+
+import random
+import numpy as np
+
+
+class QFCModel(tq.QuantumModule):
+    class QLayer(tq.QuantumModule):
+        def __init__(self):
+            super().__init__()
+            self.n_wires = 4
+            self.random_layer = tq.RandomLayer(
+                n_ops=50, wires=list(range(self.n_wires))
+            )
+
+            # gates with trainable parameters
+            self.rx0 = tq.RX(has_params=True, trainable=True)
+            self.ry0 = tq.RY(has_params=True, trainable=True)
+            self.rz0 = tq.RZ(has_params=True, trainable=True)
+            self.crx0 = tq.CRX(has_params=True, trainable=True)
+
+        @tq.static_support
+        def forward(self, q_device: tq.QuantumDevice):
+            """
+            1. To convert tq QuantumModule to qiskit or run in the static
+            model, need to:
+                (1) add @tq.static_support before the forward
+                (2) make sure to add
+                    static=self.static_mode and
+                    parent_graph=self.graph
+                    to all the tqf functions, such as tqf.hadamard below
+            """
+            self.q_device = q_device
+
+            self.random_layer(self.q_device)
+
+            # some trainable gates (instantiated ahead of time)
+            self.rx0(self.q_device, wires=0)
+            self.ry0(self.q_device, wires=1)
+            self.rz0(self.q_device, wires=3)
+            self.crx0(self.q_device, wires=[0, 2])
+
+            # add some more non-parameterized gates (add on-the-fly)
+            tqf.hadamard(
+                self.q_device, wires=3, static=self.static_mode, parent_graph=self.graph
+            )
+            tqf.sx(
+                self.q_device, wires=2, static=self.static_mode, parent_graph=self.graph
+            )
+            tqf.cnot(
+                self.q_device,
+                wires=[3, 0],
+                static=self.static_mode,
+                parent_graph=self.graph,
+            )
+            tqf.rx(
+                self.q_device,
+                wires=1,
+                params=torch.tensor([0.1]),
+                static=self.static_mode,
+                parent_graph=self.graph,
+            )
+
+    def __init__(self):
+        super().__init__()
+        self.n_wires = 4
+        self.q_device = tq.QuantumDevice(n_wires=self.n_wires)
+        self.encoder = tq.GeneralEncoder(tq.encoder_op_list_name_dict["4x4_ryzxy"])
+
+        self.q_layer = self.QLayer()
+        self.measure = tq.MeasureAll(tq.PauliZ)
+
+    def forward(self, x, use_qiskit=False):
+        self.q_device.reset_states(x.shape[0])
+        bsz = x.shape[0]
+        x = F.avg_pool2d(x, 6).view(bsz, 16)
+
+        if use_qiskit:
+            x = self.qiskit_processor.process_parameterized(
+                self.q_device, self.encoder, self.q_layer, self.measure, x
+            )
+        else:
+            self.encoder(self.q_device, x)
+            self.q_layer(self.q_device)
+            x = self.measure(self.q_device)
+
+        x = x.reshape(bsz, 2, 2).sum(-1).squeeze()
+        x = F.log_softmax(x, dim=1)
+
+        return x
+
+
+def train(dataflow, model, device, optimizer):
+    for feed_dict in dataflow["train"]:
+        inputs = feed_dict["image"].to(device)
+        targets = feed_dict["digit"].to(device)
+
+        outputs = model(inputs)
+        loss = F.nll_loss(outputs, targets)
+        optimizer.zero_grad()
+        loss.backward()
+        optimizer.step()
+        print(f"loss: {loss.item()}", end="\r")
+
+
+def valid_test(dataflow, split, model, device, qiskit=False):
+    target_all = []
+    output_all = []
+    with torch.no_grad():
+        for feed_dict in dataflow[split]:
+            inputs = feed_dict["image"].to(device)
+            targets = feed_dict["digit"].to(device)
+
+            outputs = model(inputs, use_qiskit=qiskit)
+
+            target_all.append(targets)
+            output_all.append(outputs)
+        target_all = torch.cat(target_all, dim=0)
+        output_all = torch.cat(output_all, dim=0)
+
+    _, indices = output_all.topk(1, dim=1)
+    masks = indices.eq(target_all.view(-1, 1).expand_as(indices))
+    size = target_all.shape[0]
+    corrects = masks.sum().item()
+    accuracy = corrects / size
+    loss = F.nll_loss(output_all, target_all).item()
+
+    print(f"{split} set accuracy: {accuracy}")
+    print(f"{split} set loss: {loss}")
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        "--static", action="store_true", help="compute with " "static mode"
+    )
+    parser.add_argument("--pdb", action="store_true", help="debug with pdb")
+    parser.add_argument(
+        "--wires-per-block", type=int, default=2, help="wires per block int static mode"
+    )
+    parser.add_argument(
+        "--epochs", type=int, default=5, help="number of training epochs"
+    )
+
+    args = parser.parse_args()
+
+    if args.pdb:
+        import pdb
+
+        pdb.set_trace()
+
+    seed = 0
+    random.seed(seed)
+    np.random.seed(seed)
+    torch.manual_seed(seed)
+
+    dataset = MNIST(
+        root="./mnist_data",
+        train_valid_split_ratio=[0.9, 0.1],
+        digits_of_interest=[3, 6],
+        n_test_samples=75,
+    )
+    dataflow = dict()
+
+    for split in dataset:
+        sampler = torch.utils.data.RandomSampler(dataset[split])
+        dataflow[split] = torch.utils.data.DataLoader(
+            dataset[split],
+            batch_size=256,
+            sampler=sampler,
+            num_workers=8,
+            pin_memory=True,
+        )
+
+    use_cuda = torch.cuda.is_available()
+    device = torch.device("cuda" if use_cuda else "cpu")
+
+    model = QFCModel().to(device)
+
+    n_epochs = args.epochs
+    optimizer = optim.Adam(model.parameters(), lr=5e-3, weight_decay=1e-4)
+    scheduler = CosineAnnealingLR(optimizer, T_max=n_epochs)
+
+    if args.static:
+        # optionally to switch to the static mode, which can bring speedup
+        # on training
+        model.q_layer.static_on(wires_per_block=args.wires_per_block)
+
+    for epoch in range(1, n_epochs + 1):
+        # train
+        print(f"Epoch {epoch}:")
+        train(dataflow, model, device, optimizer)
+        print(optimizer.param_groups[0]["lr"])
+
+        # valid
+        valid_test(dataflow, "valid", model, device)
+        scheduler.step()
+
+    # test
+    valid_test(dataflow, "test", model, device, qiskit=False)
+
+    # run on Qiskit simulator and real Quantum Computers
+    try:
+        from qiskit import IBMQ
+        from torchquantum.plugin import QiskitProcessor
+
+        # firstly perform simulate
+        print(f"\nTest with Qiskit Simulator")
+        processor_simulation = QiskitProcessor(use_real_qc=False)
+        model.set_qiskit_processor(processor_simulation)
+        valid_test(dataflow, "test", model, device, qiskit=True)
+
+        # then try to run on REAL QC
+        backend_name = "ibmq_lima"
+        print(f"\nTest on Real Quantum Computer {backend_name}")
+        # Please specify your own hub group and project if you have the
+        # IBMQ premium plan to access more machines.
+        processor_real_qc = QiskitProcessor(
+            use_real_qc=True,
+            backend_name=backend_name,
+            hub="ibm-q",
+            group="open",
+            project="main",
+        )
+        model.set_qiskit_processor(processor_real_qc)
+        valid_test(dataflow, "test", model, device, qiskit=True)
+    except ImportError:
+        print(
+            "Please install qiskit, create an IBM Q Experience Account and "
+            "save the account token according to the instruction at "
+            "'https://github.com/Qiskit/qiskit-ibmq-provider', "
+            "then try again."
+        )
+
+
+if __name__ == "__main__":
+    main()
diff --git a/examples/optimal_control/optimal_control.py b/examples/optimal_control/optimal_control.py
index 88624853..438e135b 100644
--- a/examples/optimal_control/optimal_control.py
+++ b/examples/optimal_control/optimal_control.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.optim as optim
 
diff --git a/examples/optimal_control/optimal_control_gaussian.py b/examples/optimal_control/optimal_control_gaussian.py
index 05fd9808..861cc92a 100644
--- a/examples/optimal_control/optimal_control_gaussian.py
+++ b/examples/optimal_control/optimal_control_gaussian.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.optim as optim
 
diff --git a/examples/optimal_control/optimal_control_multi_qubit.py b/examples/optimal_control/optimal_control_multi_qubit.py
index 184993de..023d4f3c 100644
--- a/examples/optimal_control/optimal_control_multi_qubit.py
+++ b/examples/optimal_control/optimal_control_multi_qubit.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.optim as optim
 
diff --git a/examples/param_shift_onchip_training/param_shift.py b/examples/param_shift_onchip_training/param_shift.py
index 524b1ae5..7cd8981c 100644
--- a/examples/param_shift_onchip_training/param_shift.py
+++ b/examples/param_shift_onchip_training/param_shift.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
@@ -5,9 +29,9 @@
 
 import torchquantum as tq
 import torchquantum.functional as tqf
-from torchquantum.layers import SethLayer0
+from torchquantum.layer import SethLayer0
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 
diff --git a/examples/param_shift_onchip_training/param_shift_onchip_training.ipynb b/examples/param_shift_onchip_training/param_shift_onchip_training.ipynb
index 0ff2531c..8ddba030 100644
--- a/examples/param_shift_onchip_training/param_shift_onchip_training.ipynb
+++ b/examples/param_shift_onchip_training/param_shift_onchip_training.ipynb
@@ -1490,7 +1490,7 @@
         "id": "ycs5rJMNgoYh"
       },
       "source": [
-        "Train and valid the model on ibmq_quito. You need to import `QiskitProcessor` from `torchquantum.plugins` to create a processor that handles your access to real quantum computer. You can set whether use real quantum computer or qiskit's noise model, and the backend of your quantum computer. Call `model.set_qiskit_processor` to attach the processor to your model."
+        "Train and valid the model on ibmq_quito. You need to import `QiskitProcessor` from `torchquantum.plugin` to create a processor that handles your access to real quantum computer. You can set whether use real quantum computer or qiskit's noise model, and the backend of your quantum computer. Call `model.set_qiskit_processor` to attach the processor to your model."
       ]
     },
     {
@@ -3780,7 +3780,7 @@
         }
       ],
       "source": [
-        "from torchquantum.plugins import QiskitProcessor\n",
+        "from torchquantum.plugin import QiskitProcessor\n",
         "model = Q2Model().to(device)\n",
         "processor_real_qc = QiskitProcessor(use_real_qc=True, backend_name='ibmq_quito')\n",
         "model.set_qiskit_processor(processor_real_qc)\n",
diff --git a/examples/qaoa/max_cut_backprop.py b/examples/qaoa/max_cut_backprop.py
index b6625dbb..803d16c9 100644
--- a/examples/qaoa/max_cut_backprop.py
+++ b/examples/qaoa/max_cut_backprop.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torchquantum as tq
 
diff --git a/examples/qaoa/max_cut_paramshift.py b/examples/qaoa/max_cut_paramshift.py
index c0f1f3ea..a8467c1d 100644
--- a/examples/qaoa/max_cut_paramshift.py
+++ b/examples/qaoa/max_cut_paramshift.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torchquantum as tq
 
@@ -11,7 +35,7 @@
 np.random.seed(seed)
 torch.manual_seed(seed)
 
-from torchquantum.plugins import QiskitProcessor, op_history2qiskit
+from torchquantum.plugin import QiskitProcessor, op_history2qiskit
 
        
 
diff --git a/examples/qiskit/job_manager.py b/examples/qiskit/job_manager.py
new file mode 100644
index 00000000..29addfbc
--- /dev/null
+++ b/examples/qiskit/job_manager.py
@@ -0,0 +1,61 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from qiskit import IBMQ, transpile
+from qiskit.providers.ibmq.managed import IBMQJobManager
+from qiskit.circuit.random import random_circuit
+
+import logging
+
+logging.basicConfig(level=logging.DEBUG)
+
+"""
+WARNING: seems not work on server, reasons unknown yet
+"""
+
+# import pdb
+# pdb.set_trace()
+
+provider = IBMQ.load_account()
+backend = provider.get_backend("ibmqx2")
+
+# Build a thousand circuits.
+circs = []
+for _ in range(1000):
+    circs.append(random_circuit(num_qubits=2, depth=3, measure=True))
+
+# Need to transpile the circuits first.
+circs = transpile(circs, backend=backend)
+
+print("here1")
+
+# Use Job Manager to break the circuits into multiple jobs.
+job_manager = IBMQJobManager()
+job_set_foo = job_manager.run(circs, backend=backend, name="foo")
+
+
+print("here2")
+
+results = job_set_foo.results()
+results.get_counts(5)  # Counts for experiment 5.
diff --git a/examples/qiskit/utils.py b/examples/qiskit/utils.py
index bb142198..84fd8336 100644
--- a/examples/qiskit/utils.py
+++ b/examples/qiskit/utils.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import qiskit
 
 from qiskit import IBMQ
diff --git a/examples/qiskit/vqe.py b/examples/qiskit/vqe.py
index 41cc5d44..ced7b28f 100644
--- a/examples/qiskit/vqe.py
+++ b/examples/qiskit/vqe.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 # pylint: disable=line-too-long
 from qiskit.algorithms import VQE
 from qiskit_nature.algorithms import (
diff --git a/examples/quantum_lstm/qlstm.py b/examples/quantum_lstm/qlstm.py
index 6081c7f6..b2f3e32f 100644
--- a/examples/quantum_lstm/qlstm.py
+++ b/examples/quantum_lstm/qlstm.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import numpy as np
 import torch
 import torch.nn as nn
diff --git a/examples/quantumnat/quantumnat.py b/examples/quantumnat/quantumnat.py
index 62ca5c08..14ca8182 100644
--- a/examples/quantumnat/quantumnat.py
+++ b/examples/quantumnat/quantumnat.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
@@ -5,9 +29,9 @@
 
 import torchquantum as tq
 import torchquantum.functional as tqf
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
-from torchquantum.plugins import (
+from torchquantum.plugin import (
     tq2qiskit_expand_params,
     tq2qiskit,
     qiskit2tq,
@@ -16,7 +40,7 @@
     op_history2qiskit,
     op_history2qiskit_expand_params,
 )
-from torchquantum.utils import (
+from torchquantum.util import (
     build_module_from_op_list,
     build_module_op_list,
     get_v_c_reg_mapping,
@@ -25,7 +49,7 @@
     get_cared_configs,
 )
 
-from torchquantum.plugins import QiskitProcessor
+from torchquantum.plugin import QiskitProcessor
 
 import random
 import numpy as np
diff --git a/examples/quanvolution/quanvolution.ipynb b/examples/quanvolution/quanvolution.ipynb
index 1df7d47d..5d3be2ac 100644
--- a/examples/quanvolution/quanvolution.ipynb
+++ b/examples/quanvolution/quanvolution.ipynb
@@ -1406,7 +1406,7 @@
         "# run on Qiskit simulator and real Quantum Computers\n",
         "try:\n",
         "    from qiskit import IBMQ\n",
-        "    from torchquantum.plugins import QiskitProcessor\n",
+        "    from torchquantum.plugin import QiskitProcessor\n",
         "    # firstly perform simulate\n",
         "    print(f\"\\nTest with Qiskit Simulator\")\n",
         "    processor_simulation = QiskitProcessor(use_real_qc=False)\n",
diff --git a/examples/quanvolution/quanvolution.py b/examples/quanvolution/quanvolution.py
index 6ece6e93..ada4561b 100644
--- a/examples/quanvolution/quanvolution.py
+++ b/examples/quanvolution/quanvolution.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 import torchquantum.functional as tqf
 
@@ -7,7 +31,7 @@
 import numpy as np
 import random
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 
@@ -199,7 +223,7 @@ def main():
     # run on real QC
     try:
         from qiskit import IBMQ
-        from torchquantum.plugins import QiskitProcessor
+        from torchquantum.plugin import QiskitProcessor
 
         # firstly perform simulate
         print(f"\nTest with Qiskit Simulator")
diff --git a/examples/quanvolution/quanvolution_trainable_quantum_layer.py b/examples/quanvolution/quanvolution_trainable_quantum_layer.py
index 50a51716..35c1de91 100644
--- a/examples/quanvolution/quanvolution_trainable_quantum_layer.py
+++ b/examples/quanvolution/quanvolution_trainable_quantum_layer.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 import torchquantum.functional as tqf
 
@@ -7,12 +31,12 @@
 import numpy as np
 import random
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 
 from torchquantum.encoding import encoder_op_list_name_dict
-from torchquantum.layers import U3CU3Layer0
+from torchquantum.layer import U3CU3Layer0
 
 
 class TrainableQuanvFilter(tq.QuantumModule):
diff --git a/examples/quest/core/datasets/builder.py b/examples/quest/core/datasets/builder.py
index 5adcc652..e793efe9 100644
--- a/examples/quest/core/datasets/builder.py
+++ b/examples/quest/core/datasets/builder.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn
 import torch.optim
diff --git a/examples/quest/core/datasets/circs.py b/examples/quest/core/datasets/circs.py
index 6c852985..d724f0b1 100644
--- a/examples/quest/core/datasets/circs.py
+++ b/examples/quest/core/datasets/circs.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import os
 import pdb
 import pickle
diff --git a/examples/quest/core/datasets/drawer.py b/examples/quest/core/datasets/drawer.py
index 9a97f67e..e9044c94 100644
--- a/examples/quest/core/datasets/drawer.py
+++ b/examples/quest/core/datasets/drawer.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import matplotlib.pyplot as plt
 from matplotlib import rc
 from torchpack.utils.config import configs
diff --git a/examples/quest/core/datasets/model.py b/examples/quest/core/datasets/model.py
index 01bce7c1..b638d232 100644
--- a/examples/quest/core/datasets/model.py
+++ b/examples/quest/core/datasets/model.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 from torch_geometric.nn import TransformerConv, global_mean_pool
diff --git a/examples/quest/core/datasets/trainer.py b/examples/quest/core/datasets/trainer.py
index 4b3dbd09..fbc02806 100644
--- a/examples/quest/core/datasets/trainer.py
+++ b/examples/quest/core/datasets/trainer.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 from copy import deepcopy
 
 import numpy as np
diff --git a/examples/quest/train.py b/examples/quest/train.py
index c904fae6..45b28f2c 100644
--- a/examples/quest/train.py
+++ b/examples/quest/train.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import argparse
 import pdb
 import random
diff --git a/examples/quest/utils/circ_dag_converter.py b/examples/quest/utils/circ_dag_converter.py
index 8fa266db..765271be 100644
--- a/examples/quest/utils/circ_dag_converter.py
+++ b/examples/quest/utils/circ_dag_converter.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import string
 
 import networkx as nx
diff --git a/examples/quest/utils/fide_pst.py b/examples/quest/utils/fide_pst.py
index 1a523eff..606c34d4 100644
--- a/examples/quest/utils/fide_pst.py
+++ b/examples/quest/utils/fide_pst.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import numpy as np
 import pickle
 import sys
diff --git a/examples/quest/utils/gen_app_data.py b/examples/quest/utils/gen_app_data.py
index 1feb5ad8..2c213d00 100644
--- a/examples/quest/utils/gen_app_data.py
+++ b/examples/quest/utils/gen_app_data.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import os
 import pickle
 from qiskit import QuantumCircuit
diff --git a/examples/quest/utils/gen_app_data_real.py b/examples/quest/utils/gen_app_data_real.py
index c3ba558d..578a1a7e 100644
--- a/examples/quest/utils/gen_app_data_real.py
+++ b/examples/quest/utils/gen_app_data_real.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import os
 import pickle
 from qiskit import QuantumCircuit
diff --git a/examples/quest/utils/load_data.py b/examples/quest/utils/load_data.py
index 85073c6f..b6e867ae 100644
--- a/examples/quest/utils/load_data.py
+++ b/examples/quest/utils/load_data.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import pickle
 import random
 import sys
diff --git a/examples/quest/utils/rand_circ_native.py b/examples/quest/utils/rand_circ_native.py
index 28c3616e..2bfc5783 100644
--- a/examples/quest/utils/rand_circ_native.py
+++ b/examples/quest/utils/rand_circ_native.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import pdb
 import pickle
 import random
diff --git a/examples/quest/utils/rand_circ_real.py b/examples/quest/utils/rand_circ_real.py
index 086eac95..97b99c08 100644
--- a/examples/quest/utils/rand_circ_real.py
+++ b/examples/quest/utils/rand_circ_real.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 from ast import dump
 import pdb
 import pickle
diff --git a/examples/quest/utils/run_simulator.py b/examples/quest/utils/run_simulator.py
index 201a5f9e..d8fbf1a4 100644
--- a/examples/quest/utils/run_simulator.py
+++ b/examples/quest/utils/run_simulator.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import random
 from copy import deepcopy
 
diff --git a/examples/regression/new_run_regression.py b/examples/regression/new_run_regression.py
index cea7dab5..fdeb5cd4 100644
--- a/examples/regression/new_run_regression.py
+++ b/examples/regression/new_run_regression.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
@@ -13,7 +37,7 @@
 # data is cos(theta)|000> + e^(j * phi)sin(theta) |111>
 
 from torchpack.datasets.dataset import Dataset
-from torchquantum.plugins import (
+from torchquantum.plugin import (
     tq2qiskit_initialize,
     tq2qiskit,
     tq2qiskit_measurement,
@@ -274,7 +298,7 @@ def main():
 
     try:
         from qiskit import IBMQ
-        from torchquantum.plugins import QiskitProcessor
+        from torchquantum.plugin import QiskitProcessor
 
         print(f"\nTest with Qiskit Simulator")
         processor_simulation = QiskitProcessor(use_real_qc=False)
diff --git a/examples/regression/run_regression.py b/examples/regression/run_regression.py
index 03c9fada..6c106c23 100644
--- a/examples/regression/run_regression.py
+++ b/examples/regression/run_regression.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
diff --git a/examples/save_load_example/save_load.py b/examples/save_load_example/save_load.py
index 194d54c3..1022c3aa 100644
--- a/examples/save_load_example/save_load.py
+++ b/examples/save_load_example/save_load.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 
diff --git a/examples/simple_mnist/mnist_2qubit_4class.py b/examples/simple_mnist/mnist_2qubit_4class.py
index 58682164..21a7519b 100644
--- a/examples/simple_mnist/mnist_2qubit_4class.py
+++ b/examples/simple_mnist/mnist_2qubit_4class.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 """
 use 2 qubit to perform 4 class classification,
 We can choose four different observables to measure the qubit state:
@@ -17,7 +41,7 @@
 
 from torchquantum.measurement import expval_joint_analytical
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 import random
diff --git a/examples/simple_mnist/mnist_example.py b/examples/simple_mnist/mnist_example.py
index c2c7c817..65276e91 100644
--- a/examples/simple_mnist/mnist_example.py
+++ b/examples/simple_mnist/mnist_example.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
@@ -6,14 +30,14 @@
 import numpy as np
 
 import torchquantum as tq
-from torchquantum.plugins import (
+from torchquantum.plugin import (
     tq2qiskit_measurement,
     qiskit_assemble_circs,
     op_history2qiskit,
     op_history2qiskit_expand_params,
 )
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 
@@ -222,7 +246,7 @@ def main():
     # run on Qiskit simulator and real Quantum Computers
     try:
         from qiskit import IBMQ
-        from torchquantum.plugins import QiskitProcessor
+        from torchquantum.plugin import QiskitProcessor
 
         # firstly perform simulate
         print(f"\nTest with Qiskit Simulator")
diff --git a/examples/simple_mnist/other_implementations/mnist_example_no_binding.py b/examples/simple_mnist/other_implementations/mnist_example_no_binding.py
index f5798f12..1ac849ff 100644
--- a/examples/simple_mnist/other_implementations/mnist_example_no_binding.py
+++ b/examples/simple_mnist/other_implementations/mnist_example_no_binding.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
@@ -6,14 +30,14 @@
 import torchquantum as tq
 import torchquantum.functional as tqf
 
-from torchquantum.plugins import (
+from torchquantum.plugin import (
     tq2qiskit_expand_params,
     tq2qiskit,
     tq2qiskit_measurement,
     qiskit_assemble_circs,
 )
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 import random
@@ -232,7 +256,7 @@ def main():
     # run on Qiskit simulator and real Quantum Computers
     try:
         from qiskit import IBMQ
-        from torchquantum.plugins import QiskitProcessor
+        from torchquantum.plugin import QiskitProcessor
 
         # firstly perform simulate
         print(f"\nTest with Qiskit Simulator")
diff --git a/examples/simple_mnist/other_implementations/mnist_example_with_binding.py b/examples/simple_mnist/other_implementations/mnist_example_with_binding.py
index 97fc1b7a..6b779c43 100644
--- a/examples/simple_mnist/other_implementations/mnist_example_with_binding.py
+++ b/examples/simple_mnist/other_implementations/mnist_example_with_binding.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn.functional as F
 import torch.optim as optim
@@ -6,7 +30,7 @@
 import torchquantum as tq
 import torchquantum.functional as tqf
 
-from torchquantum.datasets import MNIST
+from torchquantum.dataset import MNIST
 from torch.optim.lr_scheduler import CosineAnnealingLR
 
 import random
@@ -211,7 +235,7 @@ def main():
     # run on Qiskit simulator and real Quantum Computers
     try:
         from qiskit import IBMQ
-        from torchquantum.plugins import QiskitProcessor
+        from torchquantum.plugin import QiskitProcessor
 
         # firstly perform simulate
         print(f"\nTest with Qiskit Simulator")
diff --git a/examples/superdense_coding/README.md b/examples/superdense_coding/README.md
new file mode 100644
index 00000000..bfb4e7ee
--- /dev/null
+++ b/examples/superdense_coding/README.md
@@ -0,0 +1,13 @@
+# Superdense Coding
+
+Superdense coding is a quantum communication protocol that allows the transmission of two classical bits of information using only one qubit`[1]`. It takes advantage of quantum entanglement and the ability to manipulate qubits in superposition. Charles H. Bennett and Stephen Wiesner proposed this technique in 1970(though it was not published until 1992`[2]`) and it was experimentally realised in 1996 by Klaus Mattle, Harald Weinfurter, Paul G. Kwiat, and Anton Zeilinger utilising entangled photon pairs.
+
+## Author
+
+[Soham Bopardikar](https://github.com/bopardikarsoham)
+
+## References
+
+[1] Bennett, C.H., Brassard, G., Crépeau, C., Jozsa, R., Peres, A. and Wootters, W.K., 1993. Teleporting an unknown quantum state via dual classical and Einstein-Podolsky-Rosen channels. Physical review letters, 70(13), p.1895.
+
+[2] Bennett, C.H. and Wiesner, S.J., 1992. Communication via one-and two-particle operators on Einstein-Podolsky-Rosen states. Physical review letters, 69(20), p.2881.
\ No newline at end of file
diff --git a/examples/superdense_coding/superdense_coding_torchquantum.ipynb b/examples/superdense_coding/superdense_coding_torchquantum.ipynb
new file mode 100644
index 00000000..3f53e91c
--- /dev/null
+++ b/examples/superdense_coding/superdense_coding_torchquantum.ipynb
@@ -0,0 +1,538 @@
+{
+  "cells": [
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "dd5XGIjBjd_K"
+      },
+      "source": [
+        "**Author:** Soham Bopardikar  \n",
+        "**Advisor:** Hanrui Wang"
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "ODpUdXvMrYuD"
+      },
+      "source": [
+        "# Superdense Coding\n",
+        "Superdense coding is a quantum communication protocol that allows the transmission of two classical bits of information using only one qubit`[1]`. It takes advantage of quantum entanglement and the ability to manipulate qubits in superposition. Charles H. Bennett and Stephen Wiesner proposed this technique in 1970(though it was not published until 1992 `[2]`) and it was experimentally realised in 1996 by Klaus Mattle, Harald Weinfurter, Paul G. Kwiat, and Anton Zeilinger utilising entangled photon pairs.\n",
+        "\n",
+        "![image.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAfoAAACKCAIAAADNIh9rAAAf20lEQVR4nO3deVQTSRoA8AJDOAXkCMKABFCUQwUUEFCW8YwK6qgrjj7BY/QpyqocjrteuLs6jjMjOqIzqyujqG/Q8Vp1vQYFOVVUVFgFhuWQW64kBCEJSe8fvZuX5QiBdLpzfL8/fKa6u+rrovkSqqsrOhiGIaD1oqOjjx8/TnUUBNCYE6EKdKAG04F0DxBCOjoaciVozIlQBTpQg+lSHQAAAAAyQLoHAACtAOkeAAC0AqR7AADQCjSqAwAAaA49Pb3u7m7SmqPRaEKhkLTm1B2kewAAYbq7u8mc2KOjo0NaWxoA0r1SPo9o24cOAvtQq7oOrj1AJkj3Svk8om0fOgjsQ63qOrj2AJngVi0AQKW1tbXduHGD6ig0AaR7gBBC48ePpzoEYmjMiVBFBTswISEhIyOD6ig0ATwwrZSnxrXtSXQCz1eruk7zrj3CWy8vL/f39y8qKrKxsSGhOc0GY/d9a29v//DhA51O19XVxTBMJBJhGMZkMjs6Ourr6/X19fERUpFIJBKJnJ2dqY5XRXE4nJqamv622tvbm5mZkRmPWoBrT1pcXFx8fHyfuR4MlhLTPYZhNTU1NjY2dDodISQQCPD/qIWGhoZLly49fvw4LS1t+PDhUVFRrq6ua9eubW5uTk1Nzc3NvXv3roGBQXR0tLOz88aNG6mOV0Vdv359zZo1+vr6M2fOHDNmjI2NDZ6qkpKSampqrly5smTJEqpjVDlw7Unk5eU9f/784sWLVAeiKTDlyM7ODg0N/emnn/bt2/fw4cNNmzalpaUNqoaurq5p06Zt2bJFSRFKyOiE58+fI4RCQ0N7lBcXFyOEQkJChlCnRurvfI8fP+7o6FhUVCRdeP/+fYTQ9OnTB1WVRtK8a4/A1sVicWBg4MWLF8lpThso5dP9tWvXdu7cmZ2dzWAwEELh4eHXr1//9ttvB1UJh8N5+vRpW1ubMiKUk4GBgeRfecpBDzweb//+/R4eHpKSjx8/bty40cDA4Mcff6QwMNUH115qampnZ+fy5cupDkRzEJ/uGxoa1qxZc+LECTzXI4SMjIz8/PyMjIwQQs+fP793756xsbGHh8fs2bNl1MNgMCoqKoYPH054hOqrpaWltbV19OjR6jK3msfjsVgs6ZKEhISKiooDBw6MGTOGqqgGS+26XQMIBII9e/acOnVKVxdmDxKG+K7cs2ePWCz+/e9/LynJysr63e9+hxB6+fLl119/vXPnzu3bt+fk5Hz11Veyq7Kzs4N0j3v79m1AQICVlZWrq6u1tfXZs2epjkguISEh0jfZXr16lZiY6OnpGR8fT2FU8lPTbtcAx44dGz9+/PTp06kORLMQPjxkZ2c3f/58ycvq6mqE0IMHDzAM8/X1lYzgd3V1mZmZcTgcwgMYLBmdUFRUhBBaunRpj/LKykqEEIvFGkKdQ1BfX29hYdHjB/fTTz8R2ISC5DlfkUjk6+uro6OTm5urYFXkIKHbVf/aGyxCWm9tbWUwGG/fviWnOe1B8GBOY2NjXV3dli1bJCWPHj2i0WiBgYFsNvv58+cuLi54ub6+vpmZ2YMHD5YuXUpsDIR79uzZqlWrpEt4PB6ZARw4cKC1tbVHYVxcXGRkpBoNLxw/fjw/Pz8qKiogIIDqWOSiCt1O+bWnbGKxmMPhcLlcOp1uYGBgbm6uo6OTkJAQHh7u5uZGdXSahuB0jw+0SQ/LpqWl+fr6GhsbP3v2DMMwfAQfZ2Rk1NDQIKO2trY2IyMjfX39Adt1cnLCP/Uog5+f3/nz56VLqqqqBnyqW9kZoaWlhcBhzWHDholEIqJq6626unr37t12dnYDjuAhxbpO2SdCbLcPiPxrT9kdKBKJnjx58vjx49zc3JKSkvfv3xsbG5uamgqFws7Ozs7OzlGjRlVVVe3Zs6eoqMjT03PACin5xEOj0chc55mQRplMJsHp3tra2tPTk81m4y/T09NTU1NjY2MRQnw+H/3/zwZ/Y++vqpaWFkdHRzc3t/z8/AHbraioGHLMSrpcMOIe9mOxWPjkxR6am5stLS0JaQJ/omfIhw/Yh5s3b+bxeOfOnTM1NZUU3r59OzQ0tPfOikSi4IlII6HbVfDaU96V8Ntvv/3444+pqak2NjaffvrpunXrPDw8nJyc9PT0JPt8/PhxwYIFXl5e1dXVYWFhhoaGK1eu3LBhg7W1dX/VEviLpvGIn5mTnJwcGxtraWlZVlYmFouFQmFISAhCCP89l3534nA4Mu7EGhkZOTs7wx90CKHQ0NDeeScwMJCopIOU/Dtz5cqVW7duLViwYPHixZJCgUCQkZHRZ7pXBIEnQkK3qyBlXAnv3r3bu3dvZmbm+vXr09PTXV1d+9vz9evXpaWlxcXFRkZGGIY9e/YsOTl57Nixn3/++b59+yST/cAQKeOGQFdXV2FhIZ/PT0lJodFo7e3tGIbx+XwDA4PXr19LdtPX18/KylJGAIMioxNU5HaZSCTqMWnVysrq3bt3BDahYMAyDmez2ba2tiYmJtXV1dLlhYWFf/7zn8mMZLCo7Xaqrj1iD+/o6IiPj2cwGEeOHOHxeLKP7e+5qg8fPsTExFhbWx87dkwsFhMYrbZRyiikvr6+p6cnnU7PyMiYNGmSiYkJQohOp4eHh798+RLfp6Kigslk+vn5KSMADaOrq3v37t2kpKR58+YhhLZt2/avf/1r3LhxVMcll507d9bX1x88eNDe3l66PCUlZcSIEVRFJQ+17nZVUFRU5OfnV1dXV1hYuH37dmNjY9n79/dclbW19XfffZeVlfXLL7/MmTOnvr5eaSFrOuW9k4hEIkdHx7i4OElJW1vbnDlzrl+/np2dvXjxYvzmLeVkdEJOTg5CaPbs2T3KX79+jRAKCAgYQp0KUlLNClbb3+HZ2dk6Ojp+fn74Ol84sVicmJiop6d3/vx50iJREPnVUnXtEXX4zZs3GQxGSkqKnAfy+XwXF5eHDx/K2Ke7uzshIcHBwUEySKDUDKZ5lNVZe/fuDQkJ0dPT8/DwiImJkZR3d3fn5+dnZmbiIzyqoM8r5sWLFxEREb6+vmZmZlZWVsuXL9+zZw+GYUVFRZGRkVOmTDEzMxsxYsSyZcvi4+PlrFN50VJebX+Hz5o1CyE0YcKE0NDQ0NDQ+fPnBwcHS2673b59m7RIFERmtdRee4QcfuHCBVtb2/z8fPkPPHz48KJFi+TZ89KlSwwGA1+ICdL9oChrteju7m4ajdb7/ypIvdYcV1LNClarOuvdq2b/kFkttR2IH3758mVvb2/518loa2sbN25cenq6u7u7PPsXFhba29uPGDEC1rsfFOgsVfyVI79m1UmyqhOJmlarCul+sEf99a9/bWhoSEpKIqc5rQWdpYq/cuTXrDpJVnUiUdNq1THd83g8Op0+hO/DgHQ/KKo7xgIA0BL45D2gbLC4KEAIoWHDhlEdAjE05kSoAh2owSDdA4QQkjwPoe405kSoAh2owWDkC+np6RG+2hGNRhMKhcTWiVPNwUoC+1B5XacIJXW7el178iD5+lTNXweVBZ2lZuD6pgR0u5yU8QYmg2p+OFBZcBGrGcg7lIBuVxLpjoVOVjYYuwcAAK0A6R4AALQCpHsAANAK8JgVAEBLaduNZUj3AAAt1d3dTfK0UdLa6hMM5gAAgFaAdA8QQqjHV02pL405EapAByoI+98XT6ogSPcAIYRqa2upDoEYGnMiVIEOVNAvv/yyadMmqqPoG6R7tdHZ2VlaWooQamhogKdRSCMQCN6/f48Qqq2tJfO2HlBHAoFg165dCQkJVAfSN0j3qg7DsJ9//nnmzJkMBmPOnDkIIS8vL0dHx61bt1ZXV1MdnSZLT09fsmQJg8EIDg5GCPn7+9va2kZERLx584bq0ICKOn78uIeHx4wZM6gOpG9KTPcYhlVXVwsEAvyl5D9Afu/fv58yZcr3338fHR394cOHiooKhFBDQ0NaWpqJiYmPj8+xY8eojlEDcbncJUuWbNiwISwsrKKiorKyEiFUU1Pz5s0bHx8fFou1detWWKoF9NDW1nb48OGDBw9SHUi/lLVIRU5OzqFDh5YsWVJZWRkcHHzlypUlS5YM6k2Pz+fPmjVr4sSJx48fV0aEqq+kpGT69Onx8fFbt26VTOGSXlfk/fv3ixYtCg4OPnr0qIJtacxyJYqfCJvNDg4OnjZt2tGjR/X09HpXy+VyV61axefzb926JdlBY1C4pCX5FyGxLW7fvl0oFMr4Ckbqf8sU+V7z/ly9enXMmDGNjY34y2XLlunp6XV0dAyqksbGRjqd7unpqYQA1UB7e/vYsWOTk5N7lPf4kXG53PHjx586dUrB5pR0JZBPwRMRi8UsFmv79u2yqxWJRAsXLoyOjlakLdVE8pUg3Rz5FyGBLf773/+2srLC76uR0NzQEN98fX29qanp+fPnJSWrV68OCgqS3uHAgQPyVFVbW8vlcgmPUC3s27dv1apVvct7XzHFxcUMBqOlpUWR5ii/EImi4IlcuXJl0qRJ+NM3sqvlcrl2dnYFBQWKNKeCIN0PzdKlSw8ePEhac0NDfPNffPGFiYlJV1eXpMTFxeVPf/oThmF5eXm7du2KiIhgMpmEt6tJ+Hy+hYVFZWVl7019XjHr1q37+uuvFWmR8guRKAqeiJ+f3507d+Ss9tixYytXrlSkORUE6X4I8vLyHBwcBhzAoPy3jPjm7ezs5s+fL3mJzx558OCBpOTGjRuQ7mV78ODB1KlT+9zU5xWTlpYWGBioSIuUX4hEUeREamtrrayshEKhnNXW19dbWFj0ub/6gnQ/WGKxOCgoSHo8Q6nNKYLgmTmNjY11dXVBQUGSkkePHtFotMDAQGIb0mxFRUV+fn7y7+/r66uyD/Kpkbdv33p7e9No8i4kNXLkSFNTU3guSctdvny5o6NjxYoVVAcyMIKXSNPV1UUIjRkzRlKSlpbm6+trbGw8hNra2tqMjIz09fUH3NPJyQmfLadUNBqNnAdtDA0Nhw0bduTIkT639rfQkiILMOnq6ip7/SZyek+REzE3N//48eNgu5fJZA6tuUEh7doj4UroQUdHR3J2lC8i1hufz3/27Fl2dnZxcXFZWVlzczOPx9PV1aXT6ba2tkwm8969e7t27eLz+YaGhgPWpsgJKngNMJlMgtO9tbW1p6cnm83GX6anp6empsbGxg6hqpaWFkdHRzc3t/z8/AF3xieka4zDhw83NTV98803vTf1OZfr48ePDAaDx+OREp3GunfvXmJi4v3793tv6m8KnYuLy6+//urs7Kz86DQT5RMx+9skEonu3Llz8eLFO3fujBs3Ljg4OCQkZMOGDQwGw9jYWCwWCwSC+vr6pKQkc3Pzy5cvJyQkzJkz5/PPPw8LC5PxByLJJ9gD8QsgJycnx8bGWlpalpWVicVioVAYEhIyhHqMjIycnZ3d3NwIj1D1ubq6pqeny79/YWGh9F9UYGjGjBnz9u1bDMPk/AjG4XBaWlo++eQTZQcGyCQUCpOTk7/55hsbG5vIyMiTJ09aWFj0ueeIESMePXr06NEjDw+P1tbW69evJyYmxsTEbNu2bdOmTXQ6neTIB6aMGwJdXV2FhYV8Pj8lJYVGo7W3t0tvhVu1A2pvbzczM+tzbmWfP7L4+Phdu3YpPy7N5+bmlpeX17u8z25PSUkJCwtTflCaDKnYrdq0tDQ3NzcWi5WTkzPg4du2bdu8eXOPwmfPnoWFhY0ePfr27dsDNkcy5Ta/du1af3//HoXXrl0bNWqUUtvVABs3boyLi+td3vuKaWhosLKy6nPWJhisEydOsFis3uW9u10gEIwdO1Z6yhkYAtVJ952dnVu2bHFycrp586Y8x8p+rur+/fujR49ev349j8frszlKKHHNHLFY/PDhw2nTpklKiouL9+3bd+LECS6XGxcXl5iYqLzW1d2+ffsuXrz48OFD2bt1d3dHRERs2rTJ0dGRnMA02/r16+vq6k6cODHgnvHx8ePGjZs1axYJUQFlq6urCwwMbGpqKigoCAsLk+eQL7/8MiYmxsbGps+ts2fPLigoEAqFU6ZMUaGlDJX0NrJ3796QkBA9PT0PD4+YmBgltaLZMjIyGAzG3bt3pQulf2Q8Hm/x4sXz58/v/RQoGLLy8nI7O7sTJ05IF0p3u0gk2rFjh7u7O5vNJj06TYNU4NN9SUmJk5PTV199Jf+BeXl59vb28iwMk5iY6ODg8O7dO0wFPt0rq3npZ0807DkUMuXm5trb269du7a0tBQvwa+Yzs7OCxcuODs7b9iwgc/nUxqjBiovL58wYcLcuXOfPHmCl+Dd3t3dff/+fV9f31mzZim4agXAqUK6P3Xq1Llz5wZ1YFBQUEpKipw73759+8WLF5gGp3tAFA6Hs3v3bjs7O3d39zlz5ujr60+fPt3MzGzmzJmPHz+mOjqNJRAIkpKSxo4d6+DgMG/ePH19fRaLZW1tPXny5EuXLonFYqoD1BCqkO4H68aNGz4+PiKRiJzmCET1gpxAPhiGvXnzprS0tLi4eOrUqRMnTuxvchggVllZWUlJyZMnT6ZOnerp6QnTLolF+bz7IbT4/v17oVDo4uJCTnMEgnQPEEIoLi7u22+/pToKAmjMiVCF5A5Ux3SvLs31EQCke4BU4EIkisacCFXg6000prne4LtqAQBAK0C6BwAArQDpHgAAtALxS6QBAIBaoNFoZC65LP9XKSgrAGqbBwAAqgiFwkHt3+NeK+W3XgcLBnMAAEArQLoHAACtAOkeAAC0AqR7AADQCpDuAUJkfb82CTTmRKgCHajB1OzOMgBAk1C7iMJgwcwcdXL37t329naqowAAAApoUbrHMCwuLo7MpyoAAEB1aFG6z8rK8vHxMTExoToQAACggBal+/Pnz69atYrqKAAAgBpqdqthyLq6unx8fAoLC4cNG0Z1LACA/4JbtWSi5tN9WVlZRkbGhw8fSGvx1q1b8+bNg1wPANBaZKf7x48f+/r6Pnr0CCH0ww8/7NmzRywW97knn88PDg6Ojo4mpN3z589HREQQUhUAAKgjUlfEzMzMnDlz5rNnz7y9vRFCHA5n5cqVISEhM2bM6L0zh8N5+vRpW1ub4u02NzfX1dVNmDBB8aoAAEBdYSTy8PBgsViSl2lpaV5eXsXFxf3tX1tby+Vy5amZnEcBKV+uWnkxkHBq5PSe+vaPigRAyZlS3r2DpY69xGQyybvVUFNT4+DgEBsbS+b33OMCAgKuXr1qZ2dHcrsAANngVi2ZyBu7LysrQwiNHDmStBZxJSUlpqamkOsBAFqOvHQ/ZswYhFB1dTVpLeJguj0AACBE7tj9+PHjp02bJl3C5/Nv3rzZ3/6tra1dXV3y1Axj96pZLclNKK8Vyn/0MHavUtSxl0gdu0cIPX36dOrUqTdv3pw7dy5ecvz48YCAgMmTJ/feuaWlxdHR0c3NLT8/f8gtZmZmnjlz5ty5c0OuAQCgPDB2TyZS36P8/f2zs7M3b96ck5ODz8nx8PDoM9cjhIyMjJydnd3c3BRpsb+RnJycnNzc3Kampqqqqp07d+ITQwEAQINR8+7U2NjIZrNdXV2Vuj4ln8/HF07Q1f2/WxRisXjy5Mk5OTmGhoZPnz5duHBhXV1dj30AACSAT/dkombIzMbGxsbGRtmt3Lx5MzQ0tHce19XVXb16NT4QZmtr29zc3NnZaWxsrOx4AACAQmr27jQoCxYsOHjwoKenp4x9oqKi7Ozsdu/eTVpUAAAJ+HRPJjW7IS6/5ubmhoYGGbleLBbv378/ODh4+fLlZAYGAACU0NgB69TUVBl5vKOj49ChQxEREeHh4YcPH+7q6iIzNgAAIJ+a/TEiPxaLdfbs2T4f4hUKhf7+/gUFBfhLV1fXkpIScqMDACAEgznkUrNw5cflck1NTamOAgAgC6R7MqlZuAAATQLpnkwaO3YPAABAGqR7AADQCpDuAQBAK0C6BwAArQDpHgAAtAKkewAA0AqQ7gEAQCtAugcAAK0A6R4AALQCpHsAANAK2pXu7969297eTnUUAABAAS1K9xiGxcXFKfXrEgEAAxIIBHv37uXxeP3twOPx9u7dKxAIyIyqP+oVrWxalO6zsrJ8fHxMTEyoDgQArUan06urq8PCwvrbISwsrLq6mk6nkxlVf9QrWtm0KN2fP39+1apVVEcBAECJiYlsNnvbtm29N23bto3NZicmJpIfVX/UK1oZ1GwBzyHr6ury8fEpLCwcNmwY1bEAAFBlZaW3tzebzZZeADk9Pf2zzz4rKChgMpnUhtdD72gRQjo6Oubm5ioYbX90RSJRc3Pzhw8fEELd3d3l5eWtra2SzQKBoKqqSiQS9XmwUCh8/vz527dvxWJxj03V1dXp6enl5eW93044HM7Tp08zMzOFQuH79+8JPZ1+3bp1a968eZDrAVARTCYzISGBRqOx2Wy8ZNSoUWvWrElISFDB7Nk7WjabTaPRVDPa/gx7+PDhH/7wh/b2dhMTk0uXLnV1df3lL3/59ddfw8LCkpOTc3NzW1pa1q1bJxKJfH19pY88ffr0/v37/fz8ioqKoqKi3N3dHRwcEELd3d07duxob28fNWrUvXv3du/eHRQUZGFhgR915MiRwsJCd3d3DMPOnDnzxRdf7Nixo8/I+Hz+9OnTX758OW/ePMXP849//OP27dttbGwUrwoAQIgpU6akp6c3NDSEhIQghDgcDofD+eGHH6iOq289oj106BCGYSobbd8wDAsKCpo/f/61a9cwDMMwrKysDCG0bdu2169f4yVnz541NjZubW3F/ufkyZP29vZcLhd/+eDBgxEjRuB/6Zw5c8bR0bG4uBjfFBsb6+3tLRaLMQwrKSkJCQnBpEydOhXrR2NjI51O9/T07G8H+TU1NU2aNEnxegAAxCooKNDR0SkvLy8vL9fR0SkoKKA6IlnUK9reEIZhLBbL2toaz8gYholEIjqdvmjRIslOT548QQjl5eXhLzkcjrm5+datWyU7iMViKyurkydPYhh29epVCwuLFy9e4Jv++c9/IoR+++03DMMyMzPNzc1fvXolOfDvf/+7jOBqa2sl7yiykfP3FI1GI6EVSmIg4dTI6T317R8VCYCSM9XVVbM5I5QErOCPhslk/vd4d3d3yYR0XV1dOp3u4eEh2c/AwAAhJJlY+vLlSzabTafTc3JyJPtYWVmVlpYihBYvXrx48WKEUGVl5Zs3b/Ly8hBCHA4HIeTn58dkMr28vDw9PWfNmhUaGrpu3ToZ8dnZ2cl5JhUVFTK2BgQEXL16Vf7aAACkefXqFT48kpGR4eXlRXU4A1CvaHv473uUoaFhjw29S7D/3XStqqpCCDEYDAMpFy5c+PLLL/HdTp06FRgYeOHCBUtLy6CgIEkN+vr6jx8/3rdvn56eXlJS0owZMyIjIzElTw0qKSkxNTWFXA+AavLy8rK1tbW1tVWL7Kle0fYwlL8O3NzcEEKWlpaTJk3qvXXHjh2nTp0qKChwdnZGCEn+AsAwrLy83NTUNCEhISEh4ePHj8nJyTExMevWrQsODlbgFAYA0+0BUHG3b9+mOoRBUK9opQ1lBGrixImffPJJWlqadKFAILh16xaPxzt69GhkZCSe6xFC+BRPhNCDBw/+9re/paSk4C+NjIy2bNmydOnSoqKi/hpqa2vj8/lDiFACw7B//OMfn332mSKVAACUysXFxcXFheoo5KVe0UqjIYSEQmGPUqFQKF2I/1+SefX19U+fPh0eHl5YWDh+/Hi88NixY7NmzdLT0zM0NOzu7pYcW1ZWRqfTOzs729vbLSwsTp48GRUVJRkp4vP5U6ZM6TOylpYWR0dHNze3/Pz8AU/DycmpsrKyv61ELZxAo9GkT40SSoqBhFMjp/fUt39UJABKzpTy7h0sdewlJpOps3z58vv37+vo6MyePTsmJqa0tPTnn3/OzMy0srIKCgpKSko6cuTI/fv33717Z29vP2PGjO+//x4/OCMjY9euXZ9++umECRMKCgqCg4Pnzp2LELp27dr27duXLVsWEhLy6tWrFStWfPfdd48fP164cOGkSZNOnz7t4uISFBRkZmaWlZVla2sbHR3dZ3CdnZ3+/v5eXl6SPwiGYP369eHh4TNnzuxRnpOTk5ub29TUVFVVtXPnTm9v7yE3AQAAakHRRRTq6up4PJ6rq6t0oVgsLi4uFgqF7u7uenp6CCEul2tqatre3q6vr0+n00tLSwUCwejRo/E5P0rC5/PxhRN6zJoSi8WTJ0/OyckxNDR8+vTpwoUL6+rq1G4qGAAADIqic2z7nPGiq6vr7u4uXWJqaooQGj58OP6yx9uDkty8eTM0NLR3HtfV1V29ejU+idXW1ra5ubmzs9PY2JiEkAAAgCqavETaggULDh486OnpKWOfqKgoOzu73bt3kxYVAABQgvrHRJWkubm5oaFBRq4Xi8X79+8PDg5evnw5mYEBAAAlNHbAOjU1VUYe7+joOHToUERERHh4+OHDh7u6usiMDQAAyKexgzksFuvs2bMjR47svUkoFPr7+xcUFOAvXV1dS0pKyI0OAADIprHpHp8LRHUUAIB+NTQ0XL58eeTIkU1NTWFhYaNGjaI6IlkqKiqysrJOnz59+fJlW1tbqsMZCo0dzIFcD4CKi4yMXLp06bJly5YvX75mzRqqwxmAgYHB7Nmz2Wy2WnwLeZ80Nt0DAFRZa2trfn4+PpPb0tKyrKyspqaG6qBksbW17XNwWI1AugcAUKC2tlb6T3Bzc3MVT/caANI9AIACJiYmPB5P8pLH4xG1thXoD6R7AAAFnJycjI2N8XFw/Kv08JXVgfIMS0hIoDoGAIA28vDwuHz5sqWlZUpKyooVK3qsvKJqXr58eeHChYcPH3Z0dHC5XOnv+1MX/wGv9TUhx23A5AAAAABJRU5ErkJggg==)\n",
+        "\n",
+        "In this tutorial, we will learn how to implement superdense coding using the `torchquantum` library. We will cover the following steps:-\n",
+        "\n",
+        "### **Step 1 - Preparing the entangled state/ 2 qubit bell pair.**\n",
+        "\n",
+        "First, a bell pair of two qubits is created. Where q0 represents the sender's qubit and q1 represents the receiver's qubit. A hadamard gate is used to place q0 in a superposition of states. Then, with q0 as the control and q1 as the target, a CNOT operation is conducted.\n",
+        "\n",
+        "![image.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKgAAABWCAIAAADUsUqKAAAKx0lEQVR4nO2dW0zTXhzHD7MMHAgoN53yZyojAhMFBAUyIYJKFPEFhRcRiMSIEFR8wBsGo2A04pXwhCh7kBcTAolE5CoOUC4monKRBBBxgw0Ex2Bc1vN/qJmTjW3Atna0nwfS/mhPv9n39PS0Pb9TMwghMDXMzc3n5ub0WyaCILOzs/otk8iYmaLxZmb6l22IMokMDW8BFPhAGU9SKONJCmU8SUEUSxDCHz9+ODs70+l0AMDMzAy2YCpIJJLh4WE6nU6j0SCEcrkcQshisaRSqUAgsLCwMDMzAwDI5XK5XL5lyxa89eLMnzOez+dHRUVVVVVlZ2dXV1cnJyfX19cvtqzp6em9e/empqbqW6ROCIXCFy9eJCYmbtq0ydPTMz8/v7q6GgAgFouLi4tPnz7t4uLCZrPz8vIqKipwUUgsIIQvX75ks9lDQ0MQQgjh8ePHzc3NpVIpXCRDQ0N0Op3D4Sx2x8WCyVZLS0sLACAyMnJevLOzEwAQGhq6hDJXJIhQKExISMjLy3NycsKqAoPBCAgIYDAYi61DTk5Ovb29a9as0WfFXCSWlpaKv7rEDc3IyMjo6Kibmxt2oSEOtGvXrqEoeuzYMUWovr4+JCQEW25pabl58+b9+/d1bB6ZTCa+xhOHr1+/BgYGOjg4uLu7Ozo6Pnv2DG9F/8JkMg8fPqxoAQYGBgAAFRUVEMLW1tbo6OjZ2VkIYWZmZnZ2Nm4N07+AhZvlz58/AwCio6Pnxfv6+gAAERERSyhzCQgEgnXr1s37qQsLC/V4iGUCAADKjj5//hxBkImJCQihv79/ZWUlFpfJZLa2tuPj4/jI/BfiG5+SkqJ6jtnb26MoqsejLAcEAMBmsxXiKisr/f39raysxsbGWlpatm7disUtLCxsbW0rKiqio6M1tB+/fv1iMBgWFhaam5nNmzdjThiIDx8+nDhxQjkyMTGhdS9DX4ZHRkZoNL09OEEQZMlvqlgsFsLhcMbGxrD1mpqa4uLi9PR0AEB3dzeEULmLx2AwhEKhhuJGRkZcXV09PDyam5s1H7i3t3dpijG0OhQQEMDj8ZQj/f39JSUlmveC+ntJExER8fr1a9W4WCy2t7fX11GWA/L06dP09HR7e/uenh4URWdnZ0NDQwEA09PT4N+fGEXR8fFxDWUxGIwtW7Z4eHgYWjTxiYyMVDU+KCiIIK4DAGj+/v5v3rxhs9lpaWlMJhNBkODgYACAjY0NAEC5MRkfH9fcY1+9evWnT5+KiooMLZr4JCcnHzhwQDni4OBQUFCAlx5VaAAACwsLDodDp9Nra2v9/Pysra0BAB4eHpaWliKRSLHp2NiYr68vbkpNChqNVl5e/uTJEwBAYGDguXPnvnz5sm3bNrx1/eVvXwNF0aqqKi6Xi63S6fSYmJi2tjZstbe3l8ViBQQE4KDRNKHRaGfPngUANDQ03L9/X/F8jCD8eUlz/fr1t2/f/vz5s7y8HEXRe/fuAQAePHgQGxtrZ2fn6OiYm5vL4/GI/9oG64X8/v1bbVxzH4VU/BlvNDc3hyB/KoHyslwu//jx49TUlI+PD3YJIAJqh0m1tbU9fPiwo6Oju7vb3Nw8PDyczWbfuHHjy5cvd+/e7erq6ujooNFo+/fvd3V1vXPnji5lGkgqESCoLM2Y0Jg7whpPDcQgKZTxJIUynqRQxpMUyniSgmjfhHggCKL3N2mKO1iSQNCbjRUDdTtHQSwo40kKZTxJoYwnKZTxJIUynqRQxpMUynj9MzU1lZeXFx4evnbtWgAAnU5ns9mpqakfP37EW9pf/hoPIRwYGJiZmcFWFQsUi6KsrMzd3b22tjYtLQ0bRS6VSktLSzdu3HjkyJGEhARdRvgbAyyv4t27d5GRkYWFhdevX6+qqjpz5owih0Z3ZDIZl8tNSUnRQ6KHafLo0SMXFxc+n6+IAKUEnYmJiaSkpB07dohEIjzU/YNJpkkTk7KyMhcXl+/fvysHgUpm1qVLl0JCQrCMRBwBAoHAxsaGx+MpQvHx8cHBwYpVgUBw69YtHYsbHBz8/fu3njWaApOTk/POdQxV4+VyeVhYWH5+vrGkqQecOnXK2tpaJpMpQlu3br18+TKEsLGx8cqVK3FxcSwWCz+FpsGTJ09UMzXhArmYbW1tmzZtwiZrwQtNadIYJSUllPFaCQsLKy0tVY2rNR5C6O3t3djYaGBRmqD9/PkTy5nCqK6uRhAkKCgIj46mCdPa2qrIRdEFLpfb2tpqOD1aWTBNemnFESRNWsFycokXC3bXroraMSPW1tYoiqpNo9cRQ6VJLwGjpUkTDQihpaWlRCJRzTRaaCDG+fPnbWxssrKyjCJQDQumSS8B0qZJm5mZ/ffffz09PZ6enjru0t/fHxMTY1BVWoAQymSy9vb26enpoqIiBEEkEolyL4Dq3OlCSkpKTk6Oahyo69xJpVI7OzuxWGx4XQuyYJq0AhRFURTFp1aaDomJiY8fP5ZKpbps/Pjx4/379+M8SYKiCsjlcldX14sXLyoiHR0dmZmZYWFhdnZ26enpubm5eFRNk+HkyZNJSUnzgkDljG9vb3dycvr27ZuxdKnnj6zMzMzQ0FBzc3MvL68LFy7gq8lEkUgk3t7eGRkZyk9m5hnf3t7u6ur64sULo6ubzx9Zyo+OcX+MbLqIRKKQkJB9+/a1trZiEYXxUqk0JyfHycmJCK5DbLoz8G86AdlSC/SIg4NDZWVlQUHB0aNH165dy+Vyra2tz58/39fXV1NTExERwefz3dzc8JYJAJVQYSBQFG1paWlubq6pqeFwOJ6enuHh4apzXeIIZTxJoYZekRTKeJJCGU9SKONJCmU8SaGMJymU8SSFMp6kUMaTFMp4kkJ048vLyyUSCd4qViCEflYPIeRwOO/fvyfOxNkrBkKf8fX19b6+vpTrhoDQxvN4vHlfEaPQF8Rt6mUyma+vb3t7+6pVq/DWsgLR9Yzv6empra0dHh42qBplysrKDh06RLluILQbX1dX5+/vj32LPT8/H/sIsdot9fv9eB6PFxcXp5eiKNSgeUheXV0dgiBtbW3YaklJiZWV1UKTZehxYgSRSOTn57f8cigWQovxXl5eyh/irays3LlzZ2dn50Lb6zgxAovFMk61xn3gqOEELKdkFoulyXgsVz49PV2rkXpnz549g4ODxj8uedB0je/p6QEArF+/fsk1a2l0dXXZ2NgwmUwjH5dUaDIey5vHzntjQt2+GwPNDcL27du5XK5yZHp6Wu2cHxijo6PK0+ksBHWNx7dkLdd4CGFTUxOCIK9evVJEHj161NzcrHZjsVhsZWW1a9curcZroK6uLi4ubjklUOiCllqze/fud+/enT17ls/nY/15Ly+vXbt2qd1YLxMjLNTO8/n8hoYGkUjU39+fkZHh4+OznKNQaDnjFQiFws7OThRFDVoNZTKZp6en6jxgcrncx8dncnISQtjU1OTs7IzvXGErAF2vE87Ozs7OzgatggCA0tLSyMhIGm1+l5NGo8XHx2NXtQ0bNojF4qmpqSXP0EQBiPaSJioqKjs7m8PhaNgmOTmZyWRevXrVaKpWJATKiBaLxUKhUIPrKIpmZWXt3bs3NjbWmMJWJAR6H19cXKzBUalUevv27bi4uJiYmDt37shkMmNqW4Hg3cn4y8GDBwUCgdp/zczMKHfj3d3djaxt5fE/mu1tqHIt0joAAAAASUVORK5CYII=)\n",
+        "\n",
+        "\n",
+        "### **Step 2 - Encoding the message**\n",
+        "\n",
+        "Rules:\n",
+        "\n",
+        "\n",
+        "a) For sending 00 - Perform no operation. \n",
+        "\n",
+        "b) For sending 01 - Perform a Pauli-Z operation where q1s state is flipped.\n",
+        "\n",
+        "c) For sending 10 - Apply a Pauli-X gate. \n",
+        "\n",
+        "d) For sending 11 - Apply a Pauli-Z gate followed by a Pauli-X gate.\n",
+        "\n",
+        "### **Step 3 - Decoding the message**\n",
+        "\n",
+        "Bob gets Alice's qubit (leftmost qubit) and decodes the message sent. He does not need to know the state to decode it; instead, he simply applies the restoration operation. Bob employs a CNOT gate, with the leftmost qubit serving as control and the rightmost serving as target. Then he uses a Hadamard gate and eventually measures both qubits to extract the sent message.\n",
+        "\n",
+        "\n",
+        "![image.png](data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKgAAABWCAIAAADUsUqKAAAK40lEQVR4nO2daUwTzxvHh3VbtEU0IlSqhHqUgNREjiKIHNGfSqAaY/CKStCYGMEr4gtPjEaJ8dZojC+8aKIkBoMaRRGQQxS11kRUUNFqVFqkKIhoW+zO/8Watf/SlgXa3Zadzwuy+zA783S/M7Ozu/PMekEIAaIneDzenz9/nJsnjuNdXV3OzZM+Xkh4Onh5Of9EuSJP+mBsFYxgFyQ8R0HCcxQkPEfBqS0I4efPn0UiEZ/PBwCYTCZyA2GTjo6Or1+/8vl8DMMghGazGUIokUg6Ozu1Wq23t7eXlxcAwGw2m83mcePGse2vNX9bfE1Nzdy5c8vKyvLy8srLy7Oysqqrq3ubl9FoTExMXLdunbOddEd0Ot3ly5dXrlw5ZsyYiRMnnj59ury8HACg1+sLCgpWr14dFBQklUpPnTpVUlLCtrO2gBAWFhZKpdLm5mYIIYRw4cKFPB6vs7MT9pLm5mY+ny+TyXp7oPtDnqjuqFQqAIBCobCyNzQ0AACSk5P7kCcz4DqdbsWKFadOnQoICCCrgkAgiImJEQgEva1DAQEBGo1m6NChzqyYvaG1tfXbt28TJkwgu1kGGDx4MPWXjt19wHbu3EkQxIIFCyhTdXV1UlISua1Sqfbu3Xv06FGa/ZVYLGZF+FevXsXFxY0cOTIkJMTf3//ChQvM++BhiMXitLQ0qgf49OkTAKCkpARC+PTp0/T09K6uLghhbm5uXl4eax2TQ7Ra7YgRI6x+1/nz551YBLDTLb948QIAkJ6ebmX/8OEDACAlJaUPeTIDAABYKnrx4kUcx3/+/AkhlMvlpaWlpN1gMAwbNqy9vZ0dNx2ydu3a7hXaz8+PIAhnFTHwhMcBAFKplDpfpaWlcrlcKBS2tbWpVKrx48eTdm9v72HDhpWUlKSnpzvoP75//y4QCLy9vR13M2PHjiVPjetobW3FMIaeUjx+/Hj58uWWlp8/f9I5sD9jERzH+/zeSCKR4DKZrK2tjdy/d+9eQUFBTk4OAODNmzcQQsshnkAg0Ol0DrJrbW0NDg4OCwt78uSJ44I1Gk3fPLZJSkrKnTt3utv1er2fn59TinCsUExMjFKptLR8/PixqKiox2whey9p8HPnzuXk5Pj5+TU2NhIE0dXVlZycDAAwGo3g/38wQRDt7e0O8hIIBOPGjQsLC3O101YoFIruwk+dOtVZqg9IMLlcfvfuXalUumHDBrFYjON4fHw8AMDX1xcAYNmZtLe3Ox6xDxky5Pnz5/n5+a522oqsrKxZs2ZZWkaOHHn27FmG3fAsMACAt7e3TCbj8/kVFRVRUVE+Pj4AgLCwsMGDB7e0tFBJ29raIiMjWfPUPhiGFRcXnzx5EgAQFxe3cePGly9fhoaGsu2XW/Nv+EMQRFlZWUJCArnL5/MXLVqkVqvJXY1GI5FIYmJiWPCRBhiGZWdnAwAePHhw9OhR6mEUwh5/X9Ls2rWrqqqqqampuLiYIIjDhw8DAI4dO7Z48eLhw4f7+/sfOXJEqVSi1zZWkIOeHz9+2LQ7HhKxy9/ZP3/+/MHxv5XActtsNj979uz3798RERHkJcCdcd1kpu45q9Xq48eP19fXv3nzhsfj/ffff1KpdM+ePS9fvjx48ODr16/r6+sxDJs5c2ZwcPCBAweY9JYOA2rOHZPCu2ee9EETMTgKEp6jIOE5ChKeoyDhOQrecxIEADiOO31WD3XPzArodo6joK6eoyDhOQoSnqMg4TkKEp6jIOE5ykAT3mQyse2CZ+DxwkMICwsLFy5cGBgYCAAQCoWjR49eunTpzZs32XbNrfknPITw06dPVIvxiKbz6tUruVx+6NChtLS0p0+fAgBMJlNtbW1ycvL27dsTExOdO497QEHGVdy/f1+hUJw/f37Xrl1lZWVr1qyhYmjoYzAYEhIS1q5d2/84DzpUVFQEBAScO3eOipgBFrEpZrP5+PHjgYGBKpWKGX88C08Nk25sbBw1alR5ebmlEXQLSioqKgoKCmpqamLAJc8CaLVaX19fpVJJmTIzM+Pj46ldrVa7b98+mtl9+fLlx48fTvbRFgqF4vDhw1bG7sJDCLdv356RkcGAS54FWLVqlY+Pj8FgoEzjx4/ftm0bhPDhw4fkWZNIJOx5aAO1Wi2RSIxGo5XdpvAdHR0ikej9+/eMuOYxYLdu3UpKSqLCHD9//vzu3Tsyiio2Nnbv3r3z589nafhhl6tXry5ZsoTmXG8fH5958+bRiWTjFFhTUxMZM0VSXl6O4/jUqVNZ9KlH1Gr1tGnT6KefNm0aFRmC+MeVK1eoHmD58uVxcXGWfUJRURH9rv7bt2+WVw17SCQShn8jY4ujMDa9oj8FSSQSrHuYNLUOSm9pbW0NCgqi0xY1Gk2vLkhWxMTEVFZWdrcDO0sNFBYWzpo1qz8l0odcQMTNC9JoNHbDpPsAY2HSoaGhb9++TUxMpJn+3bt3KIbSGgihwWCoq6szGo35+fk4jnd0dFjWjl519cxw6dKlOXPmdLcDOy0+Pj7+9u3bLnbKw7AbJk1BEARBEOzUSjvMmTNHpVI9f/6cTuKqqiqtVjt9+nRXe+VhUFXAbDYHBwdv3ryZstTX1+fm5s6YMWP48OE5OTlHjhxho2ra5syZM9HR0b9+/bI0gm4tvq2tLTQ01HL0iiD5e6Zyc3OTk5N5PF54ePimTZvY9Ykmy5YtS01NtXxQaCW8Xq9PSkpav3494655AH/PlOUQkbFxaT8xmUxr1qwJCQm5du0a+Z6GEt5sNl++fFkikWzdupVcXhhhBZtLrTmF4uLiyMjIMWPGZGZmDh06NDs7e9myZSKRKD4+3uYtH4JkgEQgvH37tqqq6uHDhzweLzY2NikpiflnRJ7FABEe0Vs8fuoVom8g4TkKEp6jIOE5ChKeoyDhOQoSnqMg4TkKEp6jIOE5insJX1xc3NHRwbYXnMCNntVDCGUy2aNHj9x/mewBgBu1+Orq6sjISKQ6M7iR8Eql0uojXgjX4S5dvcFgiIyMrKurGzRoENu+cAK6Lb6xsbGiouLr168u8uPGjRupqalIdcboWfjKykq5XE5+HP306dPkR4htpuzP9+OVSmVGRkYfDkT0EcczsyorK3EcV6vV5G5RUZFQKLS3WEafF0ZoaWmJiorq7VGI/tCD8OHh4ZZfxi0tLZ08eXJDQ4O99DQXRnDRhDh214Nm2Id+Bk06Ep78pHhOTk6PQvaT2NjYL1++uLoUhCWOrvGNjY0AgFGjRvW5ZtHh9evXvr6+YrHYpaUgrHAkPPl5cbLduw50+84OjjuESZMmJSQkWFqMRuP169ftpWd3YQR0jadJD9d4CGFtbS2O47du3aIsJ06cePLkic3Eer1eKBRGR0f3KDxFZWUlWpKKFXqoNVOmTLl//352dnZNTQ05ng8PD4+OjraZuA8LI9jr52tqah48eNDS0vLx48ctW7ZERETQzxNBC5oVRKfTNTQ0UGtIOgWDwTBx4sTuQY1mszkiIoIMga6trRWJRCjw0enQvU6IRCKRSOTcOnf9+nWFQoFh1gNMDMMyMzPJa1hgYKBer//9+7dQKHRu6RyHzZc0c+fOzcvLk8lkDtJkZWWJxeIdO3Yw5hVHYG0YrNfrdTqdA9UJgti9e3diYuLixYuZdIwjsPY+vqCgwIGinZ2d+/fvz8jIWLRo0YEDBwwGA5O+cQK2BhezZ8/WarU2/2UymSyH8SEhIQz7xgX+B1itL5TTqS9rAAAAAElFTkSuQmCC)\n",
+        "\n",
+        "\n",
+        "### **Step 4 - Measurement**\n",
+        "\n",
+        "In superdense coding, measurement plays a crucial role in extracting the classical bits that Alice encoded. After Bob has applied the decoding gates, he performs a measurement on both qubits to extract the information.\n"
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "MLrQMHvMOBFB"
+      },
+      "source": [
+        "## Installation"
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "dW_Cy1QyXbcB",
+        "outputId": "796f970d-f660-453a-f1a2-ae3b84b711b7"
+      },
+      "outputs": [
+        {
+          "name": "stdout",
+          "output_type": "stream",
+          "text": [
+            "Cloning into 'torchquantum'...\n",
+            "remote: Enumerating objects: 12494, done.\u001b[K\n",
+            "remote: Counting objects: 100% (765/765), done.\u001b[K\n",
+            "remote: Compressing objects: 100% (345/345), done.\u001b[K\n",
+            "remote: Total 12494 (delta 423), reused 674 (delta 392), pack-reused 11729\u001b[K\n",
+            "Receiving objects: 100% (12494/12494), 74.92 MiB | 31.26 MiB/s, done.\n",
+            "Resolving deltas: 100% (6780/6780), done.\n"
+          ]
+        }
+      ],
+      "source": [
+        "!git clone https://github.com/mit-han-lab/torchquantum.git"
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "7QP0AcjaFdko",
+        "outputId": "8fd5df5d-1bab-4ba8-e0a1-cf1423918f5f"
+      },
+      "outputs": [
+        {
+          "name": "stdout",
+          "output_type": "stream",
+          "text": [
+            "/content/torchquantum\n"
+          ]
+        }
+      ],
+      "source": [
+        "%cd torchquantum"
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "k0v6FtlqFfyh",
+        "outputId": "892b70e9-ec49-4330-bb64-40b9dce70b9a"
+      },
+      "outputs": [
+        {
+          "name": "stdout",
+          "output_type": "stream",
+          "text": [
+            "Looking in indexes: https://pypi.org/simple, https://us-python.pkg.dev/colab-wheels/public/simple/\n",
+            "Obtaining file:///content/torchquantum\n",
+            "  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
+            "Requirement already satisfied: numpy>=1.19.2 in /usr/local/lib/python3.10/dist-packages (from torchquantum==0.1.7) (1.22.4)\n",
+            "Requirement already satisfied: torchvision>=0.9.0.dev20210130 in /usr/local/lib/python3.10/dist-packages (from torchquantum==0.1.7) (0.15.2+cu118)\n",
+            "Requirement already satisfied: tqdm>=4.56.0 in /usr/local/lib/python3.10/dist-packages (from torchquantum==0.1.7) (4.65.0)\n",
+            "Requirement already satisfied: setuptools>=52.0.0 in /usr/local/lib/python3.10/dist-packages (from torchquantum==0.1.7) (67.7.2)\n",
+            "Requirement already satisfied: torch>=1.8.0 in /usr/local/lib/python3.10/dist-packages (from torchquantum==0.1.7) (2.0.1+cu118)\n",
+            "Collecting torchpack>=0.3.0 (from torchquantum==0.1.7)\n",
+            "  Downloading torchpack-0.3.1-py3-none-any.whl (34 kB)\n",
+            "Collecting qiskit==0.38.0 (from torchquantum==0.1.7)\n",
+            "  Downloading qiskit-0.38.0.tar.gz (13 kB)\n",
+            "  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
+            "Requirement already satisfied: matplotlib>=3.3.2 in /usr/local/lib/python3.10/dist-packages (from torchquantum==0.1.7) (3.7.1)\n",
+            "Collecting pathos>=0.2.7 (from torchquantum==0.1.7)\n",
+            "  Downloading pathos-0.3.0-py3-none-any.whl (79 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m79.8/79.8 kB\u001b[0m \u001b[31m7.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting pylatexenc>=2.10 (from torchquantum==0.1.7)\n",
+            "  Downloading pylatexenc-2.10.tar.gz (162 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m162.6/162.6 kB\u001b[0m \u001b[31m15.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25h  Preparing metadata (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
+            "Collecting dill==0.3.4 (from torchquantum==0.1.7)\n",
+            "  Downloading dill-0.3.4-py2.py3-none-any.whl (86 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m86.9/86.9 kB\u001b[0m \u001b[31m3.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting qiskit-terra==0.21.2 (from qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading qiskit_terra-0.21.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (6.7 MB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m6.7/6.7 MB\u001b[0m \u001b[31m58.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting qiskit-aer==0.11.0 (from qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading qiskit_aer-0.11.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (19.2 MB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m19.2/19.2 MB\u001b[0m \u001b[31m58.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting qiskit-ibmq-provider==0.19.2 (from qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading qiskit_ibmq_provider-0.19.2-py3-none-any.whl (240 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m240.4/240.4 kB\u001b[0m \u001b[31m22.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hRequirement already satisfied: scipy>=1.0 in /usr/local/lib/python3.10/dist-packages (from qiskit-aer==0.11.0->qiskit==0.38.0->torchquantum==0.1.7) (1.10.1)\n",
+            "Requirement already satisfied: requests>=2.19 in /usr/local/lib/python3.10/dist-packages (from qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (2.27.1)\n",
+            "Collecting requests-ntlm>=1.1.0 (from qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading requests_ntlm-1.2.0-py3-none-any.whl (6.0 kB)\n",
+            "Requirement already satisfied: urllib3>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (1.26.15)\n",
+            "Requirement already satisfied: python-dateutil>=2.8.0 in /usr/local/lib/python3.10/dist-packages (from qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (2.8.2)\n",
+            "Requirement already satisfied: websocket-client>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (1.5.1)\n",
+            "Collecting websockets>=10.0 (from qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading websockets-11.0.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (129 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m129.9/129.9 kB\u001b[0m \u001b[31m13.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting retworkx>=0.11.0 (from qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading retworkx-0.12.1-py3-none-any.whl (10 kB)\n",
+            "Collecting ply>=3.10 (from qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading ply-3.11-py2.py3-none-any.whl (49 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m5.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hRequirement already satisfied: psutil>=5 in /usr/local/lib/python3.10/dist-packages (from qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7) (5.9.5)\n",
+            "Requirement already satisfied: sympy>=1.3 in /usr/local/lib/python3.10/dist-packages (from qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7) (1.11.1)\n",
+            "Collecting stevedore>=3.0.0 (from qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading stevedore-5.1.0-py3-none-any.whl (49 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.6/49.6 kB\u001b[0m \u001b[31m5.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting tweedledum<2.0,>=1.1 (from qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading tweedledum-1.1.1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (929 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m929.7/929.7 kB\u001b[0m \u001b[31m59.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting symengine>=0.9 (from qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading symengine-0.10.0-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl (37.4 MB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m37.4/37.4 MB\u001b[0m \u001b[31m18.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hRequirement already satisfied: contourpy>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.3.2->torchquantum==0.1.7) (1.0.7)\n",
+            "Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.3.2->torchquantum==0.1.7) (0.11.0)\n",
+            "Requirement already satisfied: fonttools>=4.22.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.3.2->torchquantum==0.1.7) (4.39.3)\n",
+            "Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.3.2->torchquantum==0.1.7) (1.4.4)\n",
+            "Requirement already satisfied: packaging>=20.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.3.2->torchquantum==0.1.7) (23.1)\n",
+            "Requirement already satisfied: pillow>=6.2.0 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.3.2->torchquantum==0.1.7) (8.4.0)\n",
+            "Requirement already satisfied: pyparsing>=2.3.1 in /usr/local/lib/python3.10/dist-packages (from matplotlib>=3.3.2->torchquantum==0.1.7) (3.0.9)\n",
+            "Collecting ppft>=1.7.6.6 (from pathos>=0.2.7->torchquantum==0.1.7)\n",
+            "  Downloading ppft-1.7.6.6-py3-none-any.whl (52 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m52.8/52.8 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hINFO: pip is looking at multiple versions of pathos to determine which version is compatible with other requirements. This could take a while.\n",
+            "Collecting pathos>=0.2.7 (from torchquantum==0.1.7)\n",
+            "  Downloading pathos-0.2.9-py3-none-any.whl (76 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m76.9/76.9 kB\u001b[0m \u001b[31m7.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25h  Downloading pathos-0.2.8-py2.py3-none-any.whl (81 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m81.7/81.7 kB\u001b[0m \u001b[31m9.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting multiprocess>=0.70.12 (from pathos>=0.2.7->torchquantum==0.1.7)\n",
+            "  Downloading multiprocess-0.70.14-py310-none-any.whl (134 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m134.3/134.3 kB\u001b[0m \u001b[31m13.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting pox>=0.3.0 (from pathos>=0.2.7->torchquantum==0.1.7)\n",
+            "  Downloading pox-0.3.2-py3-none-any.whl (29 kB)\n",
+            "Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from torch>=1.8.0->torchquantum==0.1.7) (3.12.0)\n",
+            "Requirement already satisfied: typing-extensions in /usr/local/lib/python3.10/dist-packages (from torch>=1.8.0->torchquantum==0.1.7) (4.5.0)\n",
+            "Requirement already satisfied: networkx in /usr/local/lib/python3.10/dist-packages (from torch>=1.8.0->torchquantum==0.1.7) (3.1)\n",
+            "Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from torch>=1.8.0->torchquantum==0.1.7) (3.1.2)\n",
+            "Requirement already satisfied: triton==2.0.0 in /usr/local/lib/python3.10/dist-packages (from torch>=1.8.0->torchquantum==0.1.7) (2.0.0)\n",
+            "Requirement already satisfied: cmake in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch>=1.8.0->torchquantum==0.1.7) (3.25.2)\n",
+            "Requirement already satisfied: lit in /usr/local/lib/python3.10/dist-packages (from triton==2.0.0->torch>=1.8.0->torchquantum==0.1.7) (16.0.5)\n",
+            "Requirement already satisfied: h5py in /usr/local/lib/python3.10/dist-packages (from torchpack>=0.3.0->torchquantum==0.1.7) (3.8.0)\n",
+            "Collecting loguru (from torchpack>=0.3.0->torchquantum==0.1.7)\n",
+            "  Downloading loguru-0.7.0-py3-none-any.whl (59 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m60.0/60.0 kB\u001b[0m \u001b[31m5.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting multimethod (from torchpack>=0.3.0->torchquantum==0.1.7)\n",
+            "  Downloading multimethod-1.9.1-py3-none-any.whl (10 kB)\n",
+            "Requirement already satisfied: pyyaml in /usr/local/lib/python3.10/dist-packages (from torchpack>=0.3.0->torchquantum==0.1.7) (6.0)\n",
+            "Requirement already satisfied: tensorboard in /usr/local/lib/python3.10/dist-packages (from torchpack>=0.3.0->torchquantum==0.1.7) (2.12.2)\n",
+            "Collecting tensorpack (from torchpack>=0.3.0->torchquantum==0.1.7)\n",
+            "  Downloading tensorpack-0.11-py2.py3-none-any.whl (296 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m296.3/296.3 kB\u001b[0m \u001b[31m26.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hRequirement already satisfied: toml in /usr/local/lib/python3.10/dist-packages (from torchpack>=0.3.0->torchquantum==0.1.7) (0.10.2)\n",
+            "INFO: pip is looking at multiple versions of multiprocess to determine which version is compatible with other requirements. This could take a while.\n",
+            "Collecting multiprocess>=0.70.12 (from pathos>=0.2.7->torchquantum==0.1.7)\n",
+            "  Downloading multiprocess-0.70.13-py310-none-any.whl (133 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m133.1/133.1 kB\u001b[0m \u001b[31m13.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25h  Downloading multiprocess-0.70.12.2-py39-none-any.whl (128 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m128.7/128.7 kB\u001b[0m \u001b[31m14.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hRequirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.8.0->qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (1.16.0)\n",
+            "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (2022.12.7)\n",
+            "Requirement already satisfied: charset-normalizer~=2.0.0 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (2.0.12)\n",
+            "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests>=2.19->qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (3.4)\n",
+            "Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.10/dist-packages (from sympy>=1.3->qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7) (1.3.0)\n",
+            "Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2->torch>=1.8.0->torchquantum==0.1.7) (2.1.2)\n",
+            "Requirement already satisfied: absl-py>=0.4 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (1.4.0)\n",
+            "Requirement already satisfied: grpcio>=1.48.2 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (1.54.0)\n",
+            "Requirement already satisfied: google-auth<3,>=1.6.3 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (2.17.3)\n",
+            "Requirement already satisfied: google-auth-oauthlib<1.1,>=0.5 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (1.0.0)\n",
+            "Requirement already satisfied: markdown>=2.6.8 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (3.4.3)\n",
+            "Requirement already satisfied: protobuf>=3.19.6 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (3.20.3)\n",
+            "Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (0.7.0)\n",
+            "Requirement already satisfied: tensorboard-plugin-wit>=1.6.0 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (1.8.1)\n",
+            "Requirement already satisfied: werkzeug>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (2.3.0)\n",
+            "Requirement already satisfied: wheel>=0.26 in /usr/local/lib/python3.10/dist-packages (from tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (0.40.0)\n",
+            "Requirement already satisfied: termcolor>=1.1 in /usr/local/lib/python3.10/dist-packages (from tensorpack->torchpack>=0.3.0->torchquantum==0.1.7) (2.3.0)\n",
+            "Requirement already satisfied: tabulate>=0.7.7 in /usr/local/lib/python3.10/dist-packages (from tensorpack->torchpack>=0.3.0->torchquantum==0.1.7) (0.8.10)\n",
+            "Requirement already satisfied: msgpack>=0.5.2 in /usr/local/lib/python3.10/dist-packages (from tensorpack->torchpack>=0.3.0->torchquantum==0.1.7) (1.0.5)\n",
+            "Collecting msgpack-numpy>=0.4.4.2 (from tensorpack->torchpack>=0.3.0->torchquantum==0.1.7)\n",
+            "  Downloading msgpack_numpy-0.4.8-py2.py3-none-any.whl (6.9 kB)\n",
+            "Requirement already satisfied: pyzmq>=16 in /usr/local/lib/python3.10/dist-packages (from tensorpack->torchpack>=0.3.0->torchquantum==0.1.7) (23.2.1)\n",
+            "Requirement already satisfied: cachetools<6.0,>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (5.3.0)\n",
+            "Requirement already satisfied: pyasn1-modules>=0.2.1 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (0.3.0)\n",
+            "Requirement already satisfied: rsa<5,>=3.1.4 in /usr/local/lib/python3.10/dist-packages (from google-auth<3,>=1.6.3->tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (4.9)\n",
+            "Requirement already satisfied: requests-oauthlib>=0.7.0 in /usr/local/lib/python3.10/dist-packages (from google-auth-oauthlib<1.1,>=0.5->tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (1.3.1)\n",
+            "Requirement already satisfied: cryptography>=1.3 in /usr/local/lib/python3.10/dist-packages (from requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (40.0.2)\n",
+            "Collecting pyspnego>=0.1.6 (from requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading pyspnego-0.9.0-py3-none-any.whl (132 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m132.7/132.7 kB\u001b[0m \u001b[31m11.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting rustworkx==0.12.1 (from retworkx>=0.11.0->qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading rustworkx-0.12.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.9 MB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.9/1.9 MB\u001b[0m \u001b[31m54.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hCollecting pbr!=2.1.0,>=2.0.0 (from stevedore>=3.0.0->qiskit-terra==0.21.2->qiskit==0.38.0->torchquantum==0.1.7)\n",
+            "  Downloading pbr-5.11.1-py2.py3-none-any.whl (112 kB)\n",
+            "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m112.7/112.7 kB\u001b[0m \u001b[31m11.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
+            "\u001b[?25hRequirement already satisfied: cffi>=1.12 in /usr/local/lib/python3.10/dist-packages (from cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (1.15.1)\n",
+            "Requirement already satisfied: pyasn1<0.6.0,>=0.4.6 in /usr/local/lib/python3.10/dist-packages (from pyasn1-modules>=0.2.1->google-auth<3,>=1.6.3->tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (0.5.0)\n",
+            "Requirement already satisfied: oauthlib>=3.0.0 in /usr/local/lib/python3.10/dist-packages (from requests-oauthlib>=0.7.0->google-auth-oauthlib<1.1,>=0.5->tensorboard->torchpack>=0.3.0->torchquantum==0.1.7) (3.2.2)\n",
+            "Requirement already satisfied: pycparser in /usr/local/lib/python3.10/dist-packages (from cffi>=1.12->cryptography>=1.3->requests-ntlm>=1.1.0->qiskit-ibmq-provider==0.19.2->qiskit==0.38.0->torchquantum==0.1.7) (2.21)\n",
+            "Building wheels for collected packages: qiskit, pylatexenc\n",
+            "  Building wheel for qiskit (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
+            "  Created wheel for qiskit: filename=qiskit-0.38.0-py3-none-any.whl size=12128 sha256=4f7f0a0ad10fc979b9d35c9ab5851f0edc5c4661e807161ab1b13170575857c8\n",
+            "  Stored in directory: /root/.cache/pip/wheels/9c/b0/59/d6281e20610c76a5f88c9b931c6b338410f70b4ba6561453bc\n",
+            "  Building wheel for pylatexenc (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
+            "  Created wheel for pylatexenc: filename=pylatexenc-2.10-py3-none-any.whl size=136820 sha256=27ea7bd84314063cf13f0bc9b2890f6314fa9969d41ba1bd4ac5be1c7ccae66c\n",
+            "  Stored in directory: /root/.cache/pip/wheels/d3/31/8b/e09b0386afd80cfc556c00408c9aeea5c35c4d484a9c762fd5\n",
+            "Successfully built qiskit pylatexenc\n",
+            "Installing collected packages: pylatexenc, ply, websockets, tweedledum, symengine, rustworkx, ppft, pox, pbr, multimethod, msgpack-numpy, loguru, dill, tensorpack, stevedore, retworkx, multiprocess, qiskit-terra, pyspnego, pathos, requests-ntlm, qiskit-aer, qiskit-ibmq-provider, qiskit, torchpack, torchquantum\n",
+            "  Running setup.py develop for torchquantum\n",
+            "Successfully installed dill-0.3.4 loguru-0.7.0 msgpack-numpy-0.4.8 multimethod-1.9.1 multiprocess-0.70.12.2 pathos-0.2.8 pbr-5.11.1 ply-3.11 pox-0.3.2 ppft-1.7.6.6 pylatexenc-2.10 pyspnego-0.9.0 qiskit-0.38.0 qiskit-aer-0.11.0 qiskit-ibmq-provider-0.19.2 qiskit-terra-0.21.2 requests-ntlm-1.2.0 retworkx-0.12.1 rustworkx-0.12.1 stevedore-5.1.0 symengine-0.10.0 tensorpack-0.11 torchpack-0.3.1 torchquantum-0.1.7 tweedledum-1.1.1 websockets-11.0.3\n"
+          ]
+        }
+      ],
+      "source": [
+        "!pip install --editable ."
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "l72ZuDsXGHGk",
+        "outputId": "6e6668bd-6657-4a4d-c2e3-ec993daadf0b"
+      },
+      "outputs": [
+        {
+          "name": "stdout",
+          "output_type": "stream",
+          "text": [
+            "env: PYTHONPATH=.\n"
+          ]
+        }
+      ],
+      "source": [
+        "%env PYTHONPATH=."
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "zRmn6K6DOL-n"
+      },
+      "source": [
+        "## Importing modules\n",
+        "\n",
+        "\n"
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "id": "YkPdVBrnFjay"
+      },
+      "outputs": [],
+      "source": [
+        "import math\n",
+        "\n",
+        "import torch\n",
+        "import torch.nn as nn\n",
+        "import torch.nn.functional as F\n",
+        "from torch.nn.utils.rnn import pad_sequence\n",
+        "import torchquantum as tq\n",
+        "import torchquantum.functional as tqf\n",
+        "import argparse\n",
+        "import tqdm\n",
+        "import time"
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "f5ueV7ixQWX6"
+      },
+      "source": [
+        "##Step 1: Preparing the 2-qubit bell pair\n",
+        "\n",
+        "To prepare an entangled state, we use the Hadamard gate (h) and the CNOT gate (cx). The Hadamard gate (h) is applied to the first qubit (qubit 0) to put it \n",
+        "into a superposition of |0⟩ and |1⟩. This creates an entangled state between the two qubits. The controlled-X gate (cx) is applied with the first qubit as the control and the second qubit as the target. It entangles the qubits further and prepares them for superdense coding. Let's wrap this all up in a function.\n"
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "id": "FT4yfAg2Fjge"
+      },
+      "outputs": [],
+      "source": [
+        "def bell_pair():\n",
+        "  qdev = tq.QuantumDevice(n_wires=2, bsz=1, device=\"cpu\")\n",
+        "  qdev.h(wires=0)\n",
+        "  qdev.cnot(wires=[0, 1])\n",
+        "  return qdev"
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "CVax-ADHRly1"
+      },
+      "source": [
+        "## Step 2: Encoding the message\n",
+        "Here, we develop a function to encrypt any message with classical bits 00, 01, 10 and 11 that Alice wishes to transmit over the channel."
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "id": "h2nTeMzzFjjS"
+      },
+      "outputs": [],
+      "source": [
+        "def encode_message(qdev, qubit, msg):\n",
+        "    if len(msg) != 2 or not set(msg).issubset({\"0\",\"1\"}):\n",
+        "        raise ValueError(f\"message '{msg}' is invalid\")\n",
+        "    if msg[1] == \"1\":\n",
+        "        qdev.x(wires=qubit)\n",
+        "    if msg[0] == \"1\":\n",
+        "        qdev.z(wires=qubit)\n",
+        "    return qdev"
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "dhEp1xzEXDBk"
+      },
+      "source": [
+        "## Step 3 - Decoding the message\n",
+        "Once Alice has encoded her message, she sends her qubit to Bob. Bob can then decode the message by applying the corresponding gates to his qubit. Bob applies a controlled-X gate (cx) with the first qubit as the control and the second qubit as the target. This operation \"transfers\" the encoded message from Alice's qubit to Bob's qubit. Then, Bob applies a Hadamard gate (h) to the first qubit. This allows Bob to extract the original classical bits."
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "id": "-_QvwabmH0nK"
+      },
+      "outputs": [],
+      "source": [
+        "def decode_message(qdev):\n",
+        "    qdev.cx(wires=[0, 1])\n",
+        "    qdev.h(wires=0)\n",
+        "    return qdev"
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "0tGZQCYQXtkg"
+      },
+      "source": [
+        "Putting all these functions together"
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "id": "NgWcSzf_IBOM"
+      },
+      "outputs": [],
+      "source": [
+        "qdev = bell_pair() # Creating the entangled pair between Alice and Bob\n",
+        "\n",
+        "message = '10'\n",
+        "qdev = encode_message(qdev, 1, message) # Encoding the message at Alice's end\n",
+        "\n",
+        "qdev = decode_message(qdev) # Decoding the original message at Bob's end"
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "BMVr6t2jZKtY"
+      },
+      "source": [
+        "## Step 4 - Measurement \n",
+        "Finally, Bob can measure the qubits to extract the encoded message. The `tq.measure` function in `torchquantum` is used to measure the qubits. This collapses the qubits into classical states, and the measurement results give us the original message bits '10' sent by Alice with a probability of 100%."
+      ]
+    },
+    {
+      "cell_type": "code",
+      "execution_count": null,
+      "metadata": {
+        "colab": {
+          "base_uri": "https://localhost:8080/"
+        },
+        "id": "5aSIUmjcgO59",
+        "outputId": "84eb1859-5ff9-45b0-c1c4-dc5d15b928a3"
+      },
+      "outputs": [
+        {
+          "name": "stdout",
+          "output_type": "stream",
+          "text": [
+            "[OrderedDict([('00', 0), ('01', 0), ('10', 1024), ('11', 0)])]\n"
+          ]
+        }
+      ],
+      "source": [
+        "print(tq.measure(qdev, n_shots=1024)) # Finally, Bob measures his qubits to read Alice's message"
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "OPSRH4sWgpr2"
+      },
+      "source": [
+        "The `tq.measure function` in `torchquantum` is used to measure the qubits. This collapses the qubits into classical states, and the measurement results give us the original message bits '10' sent by Alice with a probability of 100%."
+      ]
+    },
+    {
+      "cell_type": "markdown",
+      "metadata": {
+        "id": "nFC9-bqHbG2I"
+      },
+      "source": [
+        "# References:\n",
+        "\n",
+        "[1] Bennett, C.H., Brassard, G., Crépeau, C., Jozsa, R., Peres, A. and Wootters, W.K., 1993. Teleporting an unknown quantum state via dual classical and Einstein-Podolsky-Rosen channels. Physical review letters, 70(13), p.1895.\n",
+        "\n",
+        "[2] Bennett, C.H. and Wiesner, S.J., 1992. Communication via one-and two-particle operators on Einstein-Podolsky-Rosen states. Physical review letters, 69(20), p.2881.\n",
+        "\n",
+        "[3] [Superdense Coding - Qiskit](https://learn.qiskit.org/course/ch-algorithms/superdense-coding) \n",
+        "\n",
+        "[4] [Superdense coding - Wikipedia](https://en.wikipedia.org/wiki/Superdense_coding#:~:text=This%20protocol%20was%20first%20proposed,Zeilinger%20using%20entangled%20photon%20pairs.)"
+      ]
+    }
+  ],
+  "metadata": {
+    "colab": {
+      "provenance": []
+    },
+    "kernelspec": {
+      "display_name": "Python 3.9.1 64-bit",
+      "language": "python",
+      "name": "python3"
+    },
+    "language_info": {
+      "name": "python",
+      "version": "3.9.1"
+    },
+    "vscode": {
+      "interpreter": {
+        "hash": "f47b391bd15bf26b0169f7ceae5f0850671515af690364a96e8770f85f88a683"
+      }
+    }
+  },
+  "nbformat": 4,
+  "nbformat_minor": 0
+}
diff --git a/examples/superdense_coding/superdense_coding_torchquantum.py b/examples/superdense_coding/superdense_coding_torchquantum.py
new file mode 100644
index 00000000..4c5dd4b4
--- /dev/null
+++ b/examples/superdense_coding/superdense_coding_torchquantum.py
@@ -0,0 +1,49 @@
+import math
+
+import torch
+import torch.nn as nn
+import torch.nn.functional as F
+from torch.nn.utils.rnn import pad_sequence
+import torchquantum as tq
+import torchquantum.functional as tqf
+import argparse
+import tqdm
+import time
+
+# Preparing the entangled state/ 2 qubit bell pair.
+def bell_pair():
+  qdev = tq.QuantumDevice(n_wires=2, bsz=1, device="cpu")
+  qdev.h(wires=0)
+  qdev.cnot(wires=[0, 1])
+  return qdev
+
+# Encoding the message
+def encode_message(qdev, qubit, msg):
+    if len(msg) != 2 or not set(msg).issubset({"0","1"}):
+        raise ValueError(f"message '{msg}' is invalid")
+    if msg[1] == "1":
+        qdev.x(wires=qubit)
+    if msg[0] == "1":
+        qdev.z(wires=qubit)
+    return qdev
+
+# Decoding the message
+def decode_message(qdev):
+    qdev.cx(wires=[0, 1])
+    qdev.h(wires=0)
+    return qdev
+
+# Putting all these functions together
+def main():
+    # Creating the entangled pair between Alice and Bob
+    qdev = bell_pair()
+    # Encoding the message at Alice's end
+    message = '10'
+    qdev = encode_message(qdev, 1, message)
+    # Decoding the original message at Bob's end
+    qdev = decode_message(qdev) 
+    # Finally, Bob measures his qubits to read Alice's message
+    print(tq.measure(qdev, n_shots=1024))
+
+if __name__ == "__main__":
+    main()
\ No newline at end of file
diff --git a/examples/train_state_prep/train_state_prep.py b/examples/train_state_prep/train_state_prep.py
index 69abc73c..478a4876 100644
--- a/examples/train_state_prep/train_state_prep.py
+++ b/examples/train_state_prep/train_state_prep.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.optim as optim
 import argparse
diff --git a/examples/simple_vqe/README.md b/examples/vqe/README.md
similarity index 100%
rename from examples/simple_vqe/README.md
rename to examples/vqe/README.md
diff --git a/examples/simple_vqe/h2.txt b/examples/vqe/h2.txt
similarity index 100%
rename from examples/simple_vqe/h2.txt
rename to examples/vqe/h2.txt
diff --git a/examples/simple_vqe/h2_new.txt b/examples/vqe/h2_new.txt
similarity index 100%
rename from examples/simple_vqe/h2_new.txt
rename to examples/vqe/h2_new.txt
diff --git a/examples/simple_vqe/new_simple_vqe.py b/examples/vqe/new_simple_vqe.py
similarity index 53%
rename from examples/simple_vqe/new_simple_vqe.py
rename to examples/vqe/new_simple_vqe.py
index a0ed6f18..b5a83953 100644
--- a/examples/simple_vqe/new_simple_vqe.py
+++ b/examples/vqe/new_simple_vqe.py
@@ -1,12 +1,36 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 
-from torchquantum.algorithms import VQE, Hamiltonian
+from torchquantum.algorithm import VQE, Hamiltonian
 from qiskit import QuantumCircuit
 
-from torchquantum.plugins import qiskit2tq_op_history
+from torchquantum.plugin import qiskit2tq_op_history
 
 if __name__ == "__main__":
-    hamil = Hamiltonian.from_file("./h2.txt")
+    hamil = Hamiltonian.from_file("./examples/simple_vqe/h2.txt")
 
     ops = [
         {'name': 'u3', 'wires': 0, 'trainable': True},
diff --git a/examples/simple_vqe/new_simple_vqe_noise_model.py b/examples/vqe/new_simple_vqe_noise_model.py
similarity index 55%
rename from examples/simple_vqe/new_simple_vqe_noise_model.py
rename to examples/vqe/new_simple_vqe_noise_model.py
index c7532dec..bb0d2943 100644
--- a/examples/simple_vqe/new_simple_vqe_noise_model.py
+++ b/examples/vqe/new_simple_vqe_noise_model.py
@@ -1,10 +1,34 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 
-from torchquantum.algorithms import VQE, Hamiltonian
+from torchquantum.algorithm import VQE, Hamiltonian
 from qiskit import QuantumCircuit, transpile
 
-from torchquantum.plugins import qiskit2tq_op_history, op_history2qiskit
-from torchquantum.plugins import QiskitProcessor
+from torchquantum.plugin import qiskit2tq_op_history, op_history2qiskit
+from torchquantum.plugin import QiskitProcessor
 
 from qiskit import IBMQ
 IBMQ.load_account()
diff --git a/examples/simple_vqe/simple_vqe.py b/examples/vqe/vqe.py
similarity index 77%
rename from examples/simple_vqe/simple_vqe.py
rename to examples/vqe/vqe.py
index e3acc3a0..3f974793 100644
--- a/examples/simple_vqe/simple_vqe.py
+++ b/examples/vqe/vqe.py
@@ -1,6 +1,30 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 import torch
-from torchquantum.vqe_utils import parse_hamiltonian_file
+from torchquantum.util.vqe_utils import parse_hamiltonian_file
 import random
 import numpy as np
 import argparse
@@ -111,7 +135,7 @@ def main():
     parser.add_argument(
         "--hamil_filename",
         type=str,
-        default="./h2.txt",
+        default="examples/vqe/h2.txt",
         help="number of training epochs",
     )
 
diff --git a/setup.py b/setup.py
index 71454356..72602cb0 100644
--- a/setup.py
+++ b/setup.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 from setuptools import setup, find_packages
 
 VERSION = {}  # type: ignore
diff --git a/torchquantum/__init__.py b/torchquantum/__init__.py
index 98376237..c8aed9ed 100644
--- a/torchquantum/__init__.py
+++ b/torchquantum/__init__.py
@@ -1,22 +1,43 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 __version__ = "0.1.7"
 __author__ = "Hanrui Wang, Jiannan Cao, Jessica Ding, Jiai Gu, Song Han, Zirui Li, Zhiding Liang, Pengyu Liu, Mohammadreza Tavasoli"
 
 from .macro import *
-from .devices import *
+from .device import *
 from .module import *
-from .operators import *
+from .operator import *
 from .measurement import *
 from .functional import *
 from .graph import *
-from .layers import *
+from .layer import *
 from .encoding import *
-from .super_layers import *
-from .utils import *
+from .util import *
 from .noise_model import *
-from .node import *
-from .pulse import *
-
-# from .pulse_utils import *
+from .algorithm import *
+from .dataset import *
 
 # here we check whether the Qiskit parameterization bug is fixed, if not, a
 # warning message will be printed
diff --git a/torchquantum/__version__.py b/torchquantum/__version__.py
index d50bdb0a..0294aeef 100644
--- a/torchquantum/__version__.py
+++ b/torchquantum/__version__.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 # from setuptools import setup, find_packages
 #
 # VERSION = {}  # type: ignore
diff --git a/torchquantum/algorithm/__init__.py b/torchquantum/algorithm/__init__.py
new file mode 100644
index 00000000..623d71b7
--- /dev/null
+++ b/torchquantum/algorithm/__init__.py
@@ -0,0 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .vqe import *
+from .hamiltonian import *
+from .qft import *
diff --git a/torchquantum/algorithm/grover.py b/torchquantum/algorithm/grover.py
new file mode 100644
index 00000000..965dc7de
--- /dev/null
+++ b/torchquantum/algorithm/grover.py
@@ -0,0 +1,116 @@
+import torchquantum as tq
+
+__all__ = ["Grover"]
+
+class GroverResult(object):
+	"""Result class for Grover algorithm"""
+	def __init__(self) -> None:
+			self.iterations: int
+
+class Grover(object):
+	"""Grover's search algorithm based the paper "A fast quantum mechanical algorithm for database search" by Lov K. Grover
+	https://arxiv.org/abs/quant-ph/9605043
+	"""
+		
+	def __init__(self, oracle: tq.module.QuantumModule, iterations: int, n_wires:int) -> None:
+		"""
+		Args:
+			oracle (tq.module.QuantumModule): The oracle is a quantum module that adds a negative phase to the 
+						solution states.
+			iterations (int): The number of iterations to run the algorithm for.
+			n_wires (int): The number of qubits used in the quantum circuit.
+		"""
+		super().__init__()
+		self._oracle = oracle
+		self._iterations = iterations
+		self._n_wires = n_wires
+		
+	def initial_state_prep(self):
+		"""
+		Prepares the initial state of a quantum circuit by applying a Hadamard gate to each qubit.
+		
+		Returns:
+			a `QuantumModule` object that represents the initial state preparation circuit.
+		"""
+		ops = []
+		for i in range(self._n_wires):
+			ops.append({'name': 'hadamard', 'wires': i})
+		return tq.QuantumModule.from_op_history(ops)
+	
+	def diffusion_operator(self):
+		"""
+		Prepares the diffusion operator for the grover's circuit.
+	
+		Returns:
+			a quantum module that represents the diffusion operator for a quantum circuit.
+		"""
+		ops = []
+		hadamards = [{'name': 'hadamard', 'wires': i} for i in range(self._n_wires)]
+		flips = [{'name': 'x', 'wires': i} for i in range(self._n_wires)]
+		
+		ops += hadamards
+		ops += flips
+		
+		if self._n_wires  == 1:
+				ops += [{'name': 'z', 'wires': 0}]
+		else:
+				ops += [{'name': 'hadamard', 'wires': self._n_wires - 1}]
+				ops += [{'name': 'multicnot', 'n_wires': self._n_wires, 'wires': range(self._n_wires)}]
+				ops += [{'name': 'hadamard', 'wires': self._n_wires - 1}]
+		
+		ops += flips
+		ops += hadamards
+		
+		return tq.QuantumModule.from_op_history(ops)
+			
+					
+	def construct_grover_circuit(self, qdev: tq.QuantumDevice):
+		"""
+		Constructs a Grover's algorithm circuit with an initial state preparation, oracle,
+		and diffusion operator, and iterates through them a specified number of times.
+		
+		Args:
+			qdev (tq.QuantumDevice): tq.QuantumDevice is an object representing a quantum device or
+		simulator on which quantum circuits can be executed. 
+				
+		Returns:
+			the modified quantum device `qdev` after applying the Grover's algorithm circuit with the
+		specified number of iterations.
+		"""
+
+		self.initial_state_prep()(qdev)        
+		for _ in range(self._iterations):
+			self._oracle(qdev)
+			self.diffusion_operator()(qdev)
+		
+		return qdev
+	
+	def execute(self, qdev: tq.QuantumDevice, n_shots: int =1024):
+		"""
+		Executes a Grover search algorithm on a given quantum device and returns the result.
+		
+		Args:
+			qdev (tq.QuantumDevice): tq.QuantumDevice is an object representing a quantum device or
+		simulator on which quantum circuits can be executed. 
+			n_shots (int): The number of times the circuit is run to obtain measurement statistics.
+		Defaults to 1024
+		
+		Returns:
+			an instance of the `GroverResult` class, which contains information about the results of
+		running the Grover search algorithm on a quantum device. The `GroverResult` object includes the
+		number of iterations performed, the measured bitstring, the top measurement (i.e. the most
+		frequently measured bitstring), and the maximum probability of measuring the top measurement.
+		"""
+			
+		qdev = self.construct_grover_circuit(qdev)
+		bitstring = tq.measure(qdev, n_shots=n_shots)
+		top_measurement, max_probability = max(bitstring[0].items(), key=lambda x: x[1])
+		max_probability /= n_shots
+		
+		result = GroverResult()
+		result.iterations = self._iterations
+		result.bitstring = bitstring
+		result.top_measurement = top_measurement
+		result.max_probability = max_probability
+
+		return result
\ No newline at end of file
diff --git a/torchquantum/algorithm/hamiltonian.py b/torchquantum/algorithm/hamiltonian.py
new file mode 100644
index 00000000..54c5552c
--- /dev/null
+++ b/torchquantum/algorithm/hamiltonian.py
@@ -0,0 +1,198 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torch.nn as nn
+import torchquantum as tq
+import torchquantum.functional as tqf
+import numpy as np
+
+from typing import Any, Iterable, List
+from torchquantum.util import pauli_string_to_matrix
+
+__all__ = ["Hamiltonian"]
+
+
+def parse_hamiltonian_file(filename: str) -> dict:
+    """Parse the Hamiltonian file.
+    Args:
+        filename: The filename of the Hamiltonian file.
+    Returns:
+        A dictionary containing the information of the Hamiltonian.
+    Example file:
+        h2 bk 2
+        -1.052373245772859 I0 I1
+        0.39793742484318045 I0 Z1
+        -0.39793742484318045 Z0 I1
+        -0.01128010425623538 Z0 Z1
+        0.18093119978423156 X0 X1   
+    """
+
+    hamil_info = {}
+    hamil_info["paulis"] = []
+    hamil_info["coeffs"] = []
+
+    with open(filename, "r") as rfid:
+        lines = rfid.read().split("\n")
+
+        for k, line in enumerate(lines):
+            if not line.strip():
+                continue
+            line = line.strip()
+            if k == 0:
+                name, method, n_wires = line.split(" ")
+                hamil_info["name"] = name
+                hamil_info["method"] = method
+                hamil_info["n_wires"] = eval(n_wires)
+            else:
+                info = line.split(" ")
+                hamil_info["coeffs"].append(eval(info[0]))
+
+                pauli_string = ""
+
+                wires = []
+                obs = []
+
+                for observable in info[1:]:
+                    assert observable[0].upper() in ["X", "Y", "Z", "I"]    
+                    wires.append(int(eval(observable[1:])))
+                    obs.append(observable[0].upper())
+
+                for i in range(hamil_info["n_wires"]):
+                    if i in wires:
+                        wire_idx = wires.index(i)
+                        pauli_string += obs[wire_idx]
+                    else:
+                        pauli_string += "I"
+
+                hamil_info["paulis"].append(pauli_string)
+    
+    return hamil_info
+
+class Hamiltonian(object):
+    """Hamiltonian class."""
+    def __init__(self,
+                 coeffs: List[float],
+                 paulis: List[str],
+                 endianness: str = "big",
+                 ) -> None:
+        """Initialize the Hamiltonian.
+        Args:
+            coeffs: The coefficients of the Hamiltonian.
+            paulis: The operators of the Hamiltonian, described in strings.
+            endianness: The endianness of the operators. Default is big. Qubit 0 is the most significant bit.
+        Example:
+
+        .. code-block:: python
+            coeffs = [1.0, 1.0]
+            paulis = ["ZZ", "ZX"]
+            hamil = tq.Hamiltonian(coeffs, paulis)
+
+        """
+        if endianness not in ["big", "little"]:
+            raise ValueError("Endianness must be either big or little.")
+        if len(coeffs) != len(paulis):
+            raise ValueError("The number of coefficients and operators must be the same.")
+        for op in paulis:
+            if len(op) != len(paulis[0]):
+                raise ValueError("The length of each operator must be the same.")
+            for char in op:
+                if char not in ["X", "Y", "Z", "I"]:
+                    raise ValueError("The operator must be a string of X, Y, Z, and I.")
+        
+        self.n_wires = len(paulis[0])
+        self.coeffs = coeffs
+        self.paulis = paulis
+        self.endianness = endianness
+        if self.endianness == "little":
+            self.paulis = [pauli[::-1] for pauli in self.paulis]
+    
+    @property
+    def matrix(self) -> torch.Tensor:
+        """Return the matrix of the Hamiltonian."""
+        return self.get_matrix()
+    
+    def get_matrix(self) -> torch.Tensor:
+        """Return the matrix of the Hamiltonian."""
+        matrix = self.coeffs[0] * pauli_string_to_matrix(self.paulis[0])
+        for coeff, pauli in zip(self.coeffs[1:], self.paulis[1:]):
+            matrix += coeff * pauli_string_to_matrix(pauli)
+
+        return matrix
+    
+    def __repr__(self) -> str:
+        """Return the representation string."""
+        return f"{self.__class__.__name__}({self.coeffs}, {self.paulis}, {self.endianness})"
+    
+    def __len__(self) -> int:
+        """Return the number of terms in the Hamiltonian."""
+        return len(self.coeffs)
+    
+    @classmethod
+    def from_file(cls, file_path: str) -> Any:
+        """Initialize the Hamiltonian from a file.
+        Args:
+            file_path: The path to the file.
+        Example:
+
+        .. code-block:: python
+            hamil = tq.Hamiltonian.from_file("hamiltonian.txt")
+
+        Example of the hamiltonian.txt file:
+        h2 bk 2
+        -1.052373245772859 I0 I1
+        0.39793742484318045 I0 Z1
+        -0.39793742484318045 Z0 I1
+        -0.01128010425623538 Z0 Z1
+        0.18093119978423156 X0 X1            
+
+        """
+        hamil_info = parse_hamiltonian_file(file_path)
+        return cls(hamil_info["coeffs"], hamil_info["paulis"])
+
+
+if __name__ == '__main__':
+    import pdb
+    pdb.set_trace()
+
+    coeffs = [1.0, 1.0]
+    paulis = ["ZZ", "ZX"]
+    hamil = Hamiltonian(coeffs, paulis)
+    print(hamil.get_matrix())
+
+    coeffs = [0.6]
+    paulis = ["XXZ"]
+    hamil = Hamiltonian(coeffs, paulis)
+    print(hamil.get_matrix())
+
+    coeffs = [1.0]
+    paulis = ["II"]
+    hamil = Hamiltonian(coeffs, paulis)
+    print(hamil.get_matrix())
+
+    hamil = Hamiltonian.from_file("torchquantum/algorithms/h2.txt")
+    print(hamil.matrix)
+
+    
+
diff --git a/torchquantum/algorithm/qft.py b/torchquantum/algorithm/qft.py
new file mode 100644
index 00000000..704736e0
--- /dev/null
+++ b/torchquantum/algorithm/qft.py
@@ -0,0 +1,35 @@
+import torchquantum as tq
+from typing import Iterable
+
+__all__ = ["QFT"]
+
+
+class QFT(object):
+    def __init__(
+        self, n_wires: int = None, wires: Iterable = None, do_swaps=True
+    ) -> None:
+        """Init function for QFT class
+
+        Args:
+            n_wires (int): Number of wires for the QFT as an integer
+            wires (Iterable): Wires to perform the QFT as an Iterable
+            add_swaps (bool): Whether or not to add the final swaps in a boolean format
+            inverse (bool): Whether to create an inverse QFT layer in a boolean format
+        """
+        super().__init__()
+
+        self.n_wires = n_wires
+        self.wires = wires
+        self.do_swaps = do_swaps
+
+    def construct_qft_circuit(self) -> tq.QuantumModule:
+        """Construct the QFT circuit."""
+        return tq.layer.QFTLayer(
+            n_wires=self.n_wires, wires=self.wires, do_swaps=self.do_swaps
+        )
+
+    def construct_inverse_qft_circuit(self) -> tq.QuantumModule:
+        """Construct the inverse of a QFT circuit."""
+        return tq.layer.QFTLayer(
+            n_wires=self.n_wires, wires=self.wires, do_swaps=self.do_swaps, inverse=True
+        )
diff --git a/torchquantum/prune_utils.py b/torchquantum/algorithm/quantumnas/prune_utils.py
similarity index 55%
rename from torchquantum/prune_utils.py
rename to torchquantum/algorithm/quantumnas/prune_utils.py
index 951e9543..7c317696 100644
--- a/torchquantum/prune_utils.py
+++ b/torchquantum/algorithm/quantumnas/prune_utils.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 """
 Description: utils for pruning
 Author: Jiaqi Gu (jqgu@utexas.edu)
@@ -17,13 +41,22 @@
 
 
 class PhaseL1UnstructuredPruningMethod(torch.nn.utils.prune.BasePruningMethod):
-    """
-    Prune rotation phases which is close to -2pi, 0, +2pi, ..
-    """
+    """Prune rotation phases which are close to -2pi, 0, +2pi, etc."""
 
     PRUNING_TYPE = "unstructured"
 
     def __init__(self, amount):
+        """Initializes a PhaseL1UnstructuredPruningMethod object.
+
+        Args:
+            amount (float or int): The pruning amount. If it is a float, it represents the fraction
+                of rotation phases to prune. If it is an integer, it represents the exact number
+                of rotation phases to prune.
+
+        Example:
+            >>> pruning_method = PhaseL1UnstructuredPruningMethod(0.2)
+        """
+        
         super().__init__()
         # Check range of validity of pruning amount
         # noinspection PyProtectedMember
@@ -31,6 +64,19 @@ def __init__(self, amount):
         self.amount = amount
 
     def compute_mask(self, t, default_mask):
+        """Computes the mask for pruning the rotation phases.
+
+        Args:
+            t (torch.Tensor): The tensor containing the rotation phases.
+            default_mask (torch.Tensor): The default mask.
+
+        Returns:
+            torch.Tensor: The computed mask for pruning.
+
+        Example:
+            >>> mask = pruning_method.compute_mask(tensor, mask)
+        """
+
         t = t % (2 * np.pi)
         t[t > np.pi] -= 2 * np.pi
 
@@ -59,11 +105,21 @@ def compute_mask(self, t, default_mask):
 
 
 class ThresholdScheduler(object):
-    """
-    Smooth increasing threshold with tensorflow model pruning scheduler
-    """
+    """Smooth increasing threshold with tensorflow model pruning scheduler"""
 
     def __init__(self, step_beg, step_end, thres_beg, thres_end):
+        """Initializes a ThresholdScheduler object.
+
+        Args:
+            step_beg (int): The step at which the threshold begins to change.
+            step_end (int): The step at which the threshold stops changing.
+            thres_beg (float): The initial threshold value.
+            thres_end (float): The final threshold value.
+
+        Example:
+            >>> scheduler = ThresholdScheduler(0, 100, 0.1, 0.9)
+        """
+
         config = tf.compat.v1.ConfigProto()
         config.gpu_options.allow_growth = True
         tf.compat.v1.enable_eager_execution(config=config)
@@ -90,6 +146,15 @@ def __init__(self, step_beg, step_end, thres_beg, thres_end):
         self.global_step = 0
 
     def step(self):
+        """Computes the threshold for the current step.
+
+        Returns:
+            float: The computed threshold.
+
+        Example:
+            >>> threshold = scheduler.step()
+        """
+
         if self.global_step < self.step_beg:
             return self.thres_beg
         elif self.global_step > self.step_end:
diff --git a/torchquantum/super_layers.py b/torchquantum/algorithm/quantumnas/super_layers.py
similarity index 96%
rename from torchquantum/super_layers.py
rename to torchquantum/algorithm/quantumnas/super_layers.py
index 85f601d7..4a27d383 100644
--- a/torchquantum/super_layers.py
+++ b/torchquantum/algorithm/quantumnas/super_layers.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 import itertools
 
diff --git a/torchquantum/super_utils.py b/torchquantum/algorithm/quantumnas/super_utils.py
similarity index 97%
rename from torchquantum/super_utils.py
rename to torchquantum/algorithm/quantumnas/super_utils.py
index 5565a264..e9fa3a31 100644
--- a/torchquantum/super_utils.py
+++ b/torchquantum/algorithm/quantumnas/super_utils.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import numpy as np
 import torch.nn as nn
 from typing import Iterable
@@ -6,6 +30,44 @@
 
 
 class ArchSampler(object):
+    """
+        Architecture sampler for a neural network model.
+
+        This class provides methods to sample architectures for a neural network model.
+        It supports different sampling strategies, such as plain random sampling,
+        limiting differences between consecutive architectures, progressive sampling,
+        and more.
+
+        Args:
+            model (nn.Module): The neural network model for which architectures will be sampled.
+            strategy (dict): The sampling strategy configuration.
+            n_layers_per_block (int): The number of layers per block (if the architecture is block-based).
+
+        Attributes:
+            model (nn.Module): The neural network model.
+            total_steps (int): The total number of steps.
+            arch_space (list): The architecture space.
+            strategy (dict): The sampling strategy.
+            sample_arch_old (list): The previous sampled architecture.
+            arch_space_stage (None): The architecture space stage.
+            n_ops_smallest (int): The smallest number of operations in the space.
+            n_ops_largest (int): The largest number of operations in the space.
+            is_block_based (bool): Indicates if the architecture is block-based.
+            n_layers_per_block (int): The number of layers per block.
+            n_ops_per_chunk (list): The number of operations per chunk.
+            sample_n_ops (int): The number of operations in the sampled architecture.
+            current_stage (int): The current stage in progressive sampling.
+            current_chunk (int): The current chunk in progressive sampling.
+            step (int): The current step.
+
+        Methods:
+            set_total_steps(total_steps): Sets the total number of steps.
+            get_n_ops_per_chunk(): Separates the space into several subspaces based on the strategy.
+            get_sample_stats(sample_arch): Calculates the number of operations in a sample architecture.
+            get_space_stats(): Calculates the max and smallest number of operations in the space.
+            get_random_sample_arch(): Generates a random sample architecture.
+            get_uniform_sample_arch(): Generates a sample architecture based on the sampling strategy.
+        """
     def __init__(self, model: nn.Module, strategy=None, n_layers_per_block=None):
         self.model = model
         self.total_steps = None
diff --git a/torchquantum/algorithm/vqe.py b/torchquantum/algorithm/vqe.py
new file mode 100644
index 00000000..09580073
--- /dev/null
+++ b/torchquantum/algorithm/vqe.py
@@ -0,0 +1,136 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torch.nn as nn
+import torchquantum as tq
+
+from torchpack.utils.logging import logger
+from torchquantum.measurement import expval_joint_analytical
+
+
+__all__ = ["VQE"]
+
+
+class VQE(object):
+    """The Variational Quantum Eigensolver (VQE).
+    
+    Attributes:
+        hamil: A dictionary containing information about the Hamiltonian.
+        ansatz: An Ansatz object.
+        train_configs: A dictionary containing training configurations.
+        n_wires: An integer number of wires in the Hamiltonian.
+        n_epochs: An integer number of training epochs.
+        n_steps: An integer number of optimization steps per epoch.
+        optimizer_name: Name of the optimizer.
+        scheduler_name: Name of the learning rate scheduler.
+        lr: A float indicating learning rate.
+        device: Device to use for training.
+        
+    Methods:
+        __init__: Initialize the VQE object.
+        get_expval: Calculate the expectation value of the Hamiltonian for a given quantum device.
+        get_loss: Calculate the loss function.
+        train: Train the VQE model.
+    """
+    
+    def __init__(self, hamil, ansatz, train_configs) -> None:
+        """Initialize the VQE object.
+    
+        Args:
+            hamil (dict): Information about the Hamiltonian
+            ansatz (Ansatz): An Ansatz object representing the variational circuit
+            train_configs (dict): Configuration parameters for training the VQE model
+            
+        """
+        self.hamil = hamil
+        self.ansatz = ansatz
+        self.train_configs = train_configs
+
+        self.n_wires = hamil.n_wires
+        self.n_epochs = self.train_configs.get("n_epochs", 100)
+        self.n_steps = self.train_configs.get("n_steps", 10)
+        self.optimizer_name = self.train_configs.get("optimizer", "Adam")
+        self.scheduler_name = self.train_configs.get("scheduler", "CosineAnnealingLR")
+        self.lr = self.train_configs.get("lr", 0.1)
+        self.device = self.train_configs.get("device", "cpu")
+        self.ansatz = self.ansatz.to(self.device)
+
+    def get_expval(self, qdev):
+        """Calculate the expectation value of the Hamiltonian for a given quantum device.
+
+        Args:
+            qdev (torchquantum.QuantumDevice): Quantum device representing the state of the variational circuit
+
+        Returns:
+            float : expectation value of the Hamiltonian
+        """
+        
+        hamil_list = self.hamil.hamil_info["hamil_list"]
+        expval = 0
+        for hamil in hamil_list:
+            expval += (
+                expval_joint_analytical(qdev, observable=hamil["pauli_string"])
+                * hamil["coeff"]
+            )
+        return expval
+
+    def get_loss(self):
+        """Calculate the loss function.
+        
+        Returns:
+            float: loss value
+        """
+        
+        qdev = tq.QuantumDevice(
+            n_wires=self.n_wires,
+            bsz=1,
+            device=self.device,
+        )
+        self.ansatz(qdev)
+        expval = self.get_expval(qdev)
+        return expval
+    
+    def train(self):
+        """Train the VQE model.
+
+        Returns:
+            float: final loss value
+        """
+        
+        optimizer = getattr(torch.optim, self.optimizer_name)(self.ansatz.parameters(), lr=self.lr)
+        lr_scheduler = getattr(torch.optim.lr_scheduler, self.scheduler_name)(optimizer, T_max=self.n_epochs)
+        loss = None
+        for epoch in range(self.n_epochs):
+            for step in range(self.n_steps):
+                loss = self.get_loss()
+                optimizer.zero_grad()
+                loss.backward()
+                optimizer.step()
+                print(f"Epoch: {epoch}, Step: {step}, Loss: {loss}")
+            lr_scheduler.step()
+        return loss.detach().cpu().item()
+
+# if __name__ == '__main__':
+    # ansatz = Ansatz()
diff --git a/torchquantum/algorithms/__init__.py b/torchquantum/algorithms/__init__.py
deleted file mode 100644
index 18424648..00000000
--- a/torchquantum/algorithms/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-from .vqe import *
-from .hamiltonian import *
\ No newline at end of file
diff --git a/torchquantum/algorithms/hamiltonian.py b/torchquantum/algorithms/hamiltonian.py
deleted file mode 100644
index f9fc8855..00000000
--- a/torchquantum/algorithms/hamiltonian.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import torch.nn as nn
-import torchquantum as tq
-import torchquantum.functional as tqf
-import numpy as np
-
-from typing import Iterable
-from torchquantum.plugins.qiskit_macros import QISKIT_INCOMPATIBLE_FUNC_NAMES
-from torchpack.utils.logging import logger
-from torchquantum.vqe_utils import parse_hamiltonian_file
-
-
-__all__ = ["Hamiltonian"]
-
-class Hamiltonian(object):
-    def __init__(self, hamil_info) -> None:
-        self.hamil_info = self.process_hamil_info(hamil_info)
-        self.n_wires = hamil_info["n_wires"]
-
-    def process_hamil_info(self, hamil_info):
-        hamil_list = hamil_info["hamil_list"]
-        n_wires = hamil_info["n_wires"]
-        all_info = []
-
-        for hamil in hamil_list:
-            pauli_string = ""
-            for i in range(n_wires):
-                if i in hamil["wires"]:
-                    wire = hamil["wires"].index(i)
-                    pauli_string += hamil["observables"][wire].upper()
-                else:
-                    pauli_string += "I"
-            all_info.append({"pauli_string": pauli_string, "coeff": hamil["coefficient"]})
-        hamil_info["hamil_list"] = all_info
-        return hamil_info
-
-    @classmethod
-    def from_file(cls, file_path):
-        hamil_info = parse_hamiltonian_file(file_path)
-        return cls(hamil_info)
-    
\ No newline at end of file
diff --git a/torchquantum/algorithms/vqe.py b/torchquantum/algorithms/vqe.py
deleted file mode 100644
index e01aebc2..00000000
--- a/torchquantum/algorithms/vqe.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import torch
-import torch.nn as nn
-import torchquantum as tq
-import torchquantum.functional as tqf
-import numpy as np
-
-from typing import Iterable
-from torchquantum.plugins.qiskit_macros import QISKIT_INCOMPATIBLE_FUNC_NAMES
-from torchpack.utils.logging import logger
-from torchquantum.measurement import expval_joint_analytical
-
-
-__all__ = ["VQE"]
-
-
-class VQE(object):
-    def __init__(self, hamil, ansatz, train_configs) -> None:
-        """Init function for VQE class
-        Args:
-            hamil (dict): A dictionary containing the information of the hamiltonian
-         ansatz (Ansatz): An Ansatz object
-        """
-        self.hamil = hamil
-        self.ansatz = ansatz
-        self.train_configs = train_configs
-
-        self.n_wires = hamil.n_wires
-        self.n_epochs = self.train_configs.get("n_epochs", 100)
-        self.n_steps = self.train_configs.get("n_steps", 10)
-        self.optimizer_name = self.train_configs.get("optimizer", "Adam")
-        self.scheduler_name = self.train_configs.get("scheduler", "CosineAnnealingLR")
-        self.lr = self.train_configs.get("lr", 0.1)
-        self.device = self.train_configs.get("device", "cpu")
-        self.ansatz = self.ansatz.to(self.device)
-
-    def get_expval(self, qdev):
-        hamil_list = self.hamil.hamil_info["hamil_list"]
-        expval = 0
-        for hamil in hamil_list:
-            expval += (
-                expval_joint_analytical(qdev, observable=hamil["pauli_string"])
-                * hamil["coeff"]
-            )
-        return expval
-
-    def get_loss(self):
-        qdev = tq.QuantumDevice(
-            n_wires=self.n_wires,
-            bsz=1,
-            device=self.device,
-        )
-        self.ansatz(qdev)
-        expval = self.get_expval(qdev)
-        return expval
-    
-    def train(self):
-        optimizer = getattr(torch.optim, self.optimizer_name)(self.ansatz.parameters(), lr=self.lr)
-        lr_scheduler = getattr(torch.optim.lr_scheduler, self.scheduler_name)(optimizer, T_max=self.n_epochs)
-        loss = None
-        for epoch in range(self.n_epochs):
-            for step in range(self.n_steps):
-                loss = self.get_loss()
-                optimizer.zero_grad()
-                loss.backward()
-                optimizer.step()
-                print(f"Epoch: {epoch}, Step: {step}, Loss: {loss}")
-            lr_scheduler.step()
-        return loss.detach().cpu().item()
-
-# if __name__ == '__main__':
-    # ansatz = Ansatz()
diff --git a/torchquantum/dataset/__init__.py b/torchquantum/dataset/__init__.py
new file mode 100644
index 00000000..858d5134
--- /dev/null
+++ b/torchquantum/dataset/__init__.py
@@ -0,0 +1,29 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .mnist import *
+from .vowel import *
+from .layer_regression import *
+from .vqe import *
+from .cifar10 import *
diff --git a/torchquantum/datasets/cifar10.py b/torchquantum/dataset/cifar10.py
similarity index 86%
rename from torchquantum/datasets/cifar10.py
rename to torchquantum/dataset/cifar10.py
index b727df83..8aa5bc53 100644
--- a/torchquantum/datasets/cifar10.py
+++ b/torchquantum/dataset/cifar10.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 
 from torchpack.datasets.dataset import Dataset
diff --git a/torchquantum/dataset/layer_regression.py b/torchquantum/dataset/layer_regression.py
new file mode 100644
index 00000000..37f1088c
--- /dev/null
+++ b/torchquantum/dataset/layer_regression.py
@@ -0,0 +1,163 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from torchpack.datasets.dataset import Dataset
+import numpy as np
+import torch
+
+__all__ = ["LayerRegression"]
+
+
+class LayerRegressionDatasetV:
+    """Layer Regression Dataset with Variational Input"""
+
+    def __init__(self):
+        """Initializes a LayerRegressionDatasetV object.
+
+        Example:
+            >>> dataset = LayerRegressionDatasetV()
+        """
+
+        self.data = None
+        self.n_instance = 10000
+        self.input = np.random.rand(5).astype(np.float) * 2 * np.pi
+        self.output = np.random.rand(5).astype(np.float) * 2 - 1
+
+    def __getitem__(self, index: int):
+        """Gets an instance from the dataset.
+
+        Args:
+            index (int): The index of the instance.
+
+        Returns:
+            dict: A dictionary containing the input and output.
+
+        Example:
+            >>> dataset = LayerRegressionDatasetV()
+            >>> instance = dataset[0]
+        """
+        
+        instance = {"input": self.input, "output": self.output}
+        return instance
+
+    def __len__(self) -> int:
+        """Returns the number of instances in the dataset.
+
+        Returns:
+            int: The number of instances.
+
+        Example:
+            >>> dataset = LayerRegressionDatasetV()
+            >>> length = len(dataset)
+        """
+        
+        return self.n_instance
+
+
+class LayerRegressionV(Dataset):
+    """Layer Regression Dataset with Variational Input"""
+    
+    def __init__(
+        self,
+    ):
+        """Initializes a LayerRegressionV object.
+
+        Example:
+            >>> dataset = LayerRegressionV()
+        """
+        
+        super().__init__(
+            {split: LayerRegressionDatasetV() for split in ["train", "valid", "test"]}
+        )
+
+
+class LayerRegressionDataset:
+    """Layer Regression Dataset
+    
+    Attributes:
+        data: The dataset.
+        n_instance (int): The number of instances.
+        output: The output data.
+    """
+    
+    def __init__(self):
+        """Initializes a LayerRegressionDataset object.
+
+        Example:
+            >>> dataset = LayerRegressionDataset()
+        """
+        
+        self.data = None
+        self.n_instance = 10000
+        mat = torch.randn((2**5, 2**5), dtype=torch.complex64)
+        mat = mat.svd()[0].data
+
+        self.output = mat
+
+    def __getitem__(self, index: int):
+        """Gets an instance from the dataset.
+
+        Args:
+            index (int): The index of the instance.
+
+        Returns:
+            dict: A dictionary containing the input and output.
+
+        Example:
+            >>> dataset = LayerRegressionDataset()
+            >>> instance = dataset[0]
+        """
+        
+        instance = {"input": self.output, "output": self.output}
+        return instance
+
+    def __len__(self) -> int:
+        """Returns the number of instances in the dataset.
+
+        Returns:
+            int: The number of instances.
+
+        Example:
+            >>> dataset = LayerRegressionDataset()
+            >>> length = len(dataset)
+        """
+        
+        return self.n_instance
+
+
+class LayerRegression(Dataset):
+    """Layer Regression Dataset"""
+    
+    def __init__(
+        self,
+    ):
+        """Initializes a LayerRegression object.
+
+        Example:
+            >>> dataset = LayerRegression()
+        """
+        
+        super().__init__(
+            {split: LayerRegressionDataset() for split in ["train", "valid", "test"]}
+        )
diff --git a/torchquantum/datasets/mnist.py b/torchquantum/dataset/mnist.py
similarity index 89%
rename from torchquantum/datasets/mnist.py
rename to torchquantum/dataset/mnist.py
index 89953b9f..78d8ac5f 100644
--- a/torchquantum/datasets/mnist.py
+++ b/torchquantum/dataset/mnist.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 
 from torchpack.datasets.dataset import Dataset
diff --git a/torchquantum/datasets/vowel.py b/torchquantum/dataset/vowel.py
similarity index 91%
rename from torchquantum/datasets/vowel.py
rename to torchquantum/dataset/vowel.py
index 56908211..209db361 100644
--- a/torchquantum/datasets/vowel.py
+++ b/torchquantum/dataset/vowel.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 """
 Description:
 Author: Jiaqi Gu (jqgu@utexas.edu)
diff --git a/torchquantum/dataset/vqe.py b/torchquantum/dataset/vqe.py
new file mode 100644
index 00000000..eee575eb
--- /dev/null
+++ b/torchquantum/dataset/vqe.py
@@ -0,0 +1,92 @@
+from torchpack.datasets.dataset import Dataset
+
+
+__all__ = ["VQE"]
+
+
+class VQEDataset:
+    """Dataset for VQE.
+    
+    Attributes:
+        split (str): Split of the dataset ("train", "valid", "test").
+        steps_per_epoch (int): Number of steps per epoch.
+    
+    Methods:
+        __getitem__: Get an item from the dataset
+        __len__: Get the length of the dataset
+        
+    Examples:
+        >>> dataset = VQEDataset(split='train', steps_per_epoch=100)
+        >>> instance = dataset[0]
+    """
+    
+    def __init__(self, split, steps_per_epoch):
+        """Initialize the VQEDataset.
+
+        Args:
+            split (str): Split of the dataset ("train", "valid", "test")
+            steps_per_epoch (int): Number of steps per epoch
+        """
+        
+        self.split = split
+        self.steps_per_epoch = steps_per_epoch
+
+    def __getitem__(self, index: int):
+        """Get an instance from the dataset.
+        
+        Args:
+            index (int): Index of the item
+
+        Returns:
+            dict: instance containing the input and target
+        
+        Examples:
+            >>> instance = dataset[0]
+        """
+        
+        instance = {"input": -1, "target": -1}
+
+        return instance
+
+    def __len__(self) -> int:
+        """Get the length of the dataset.
+
+        Returns:
+            int: length of the dataset
+            
+        Examples:
+            >>> length = len(dataset)
+        """
+        
+        if self.split == "train":
+            return self.steps_per_epoch
+        else:
+            return 1
+
+
+class VQE(Dataset):
+    """Dataset for the VQE.
+
+    Attributes:
+        steps_per_epoch (int): Number of steps per epoch
+
+    Methods:
+        __init__: Initialize the VQE dataset
+    
+    Examples:
+        >>> dataset = VQE(steps_per_epoch=100)
+    """
+    
+    def __init__(self, steps_per_epoch):
+        """Initialize the VQE dataset.
+
+        Args:
+            steps_per_epoch (int): Number of steps per epoch
+        """
+        
+        super().__init__(
+            {
+                split: VQEDataset(split=split, steps_per_epoch=steps_per_epoch)
+                for split in ["train", "valid", "test"]
+            }
+        )
diff --git a/torchquantum/datasets/__init__.py b/torchquantum/datasets/__init__.py
deleted file mode 100644
index 63d6541e..00000000
--- a/torchquantum/datasets/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from .mnist import *
-from .vowel import *
-from .layer_regression import *
-from .vqe import *
-from .cifar10 import *
diff --git a/torchquantum/datasets/layer_regression.py b/torchquantum/datasets/layer_regression.py
deleted file mode 100644
index 7ea78d79..00000000
--- a/torchquantum/datasets/layer_regression.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from torchpack.datasets.dataset import Dataset
-import numpy as np
-import torch
-
-__all__ = ["LayerRegression"]
-
-
-class LayerRegressionDatasetV:
-    def __init__(self):
-        self.data = None
-        self.n_instance = 10000
-        self.input = np.random.rand(5).astype(np.float) * 2 * np.pi
-        self.output = np.random.rand(5).astype(np.float) * 2 - 1
-
-    def __getitem__(self, index: int):
-        instance = {"input": self.input, "output": self.output}
-        return instance
-
-    def __len__(self) -> int:
-        return self.n_instance
-
-
-class LayerRegressionV(Dataset):
-    def __init__(
-        self,
-    ):
-        super().__init__(
-            {split: LayerRegressionDatasetV() for split in ["train", "valid", "test"]}
-        )
-
-
-class LayerRegressionDataset:
-    def __init__(self):
-        self.data = None
-        self.n_instance = 10000
-        mat = torch.randn((2**5, 2**5), dtype=torch.complex64)
-        mat = mat.svd()[0].data
-
-        self.output = mat
-
-    def __getitem__(self, index: int):
-        instance = {"input": self.output, "output": self.output}
-        return instance
-
-    def __len__(self) -> int:
-        return self.n_instance
-
-
-class LayerRegression(Dataset):
-    def __init__(
-        self,
-    ):
-        super().__init__(
-            {split: LayerRegressionDataset() for split in ["train", "valid", "test"]}
-        )
diff --git a/torchquantum/datasets/vqe.py b/torchquantum/datasets/vqe.py
deleted file mode 100644
index 2a003a22..00000000
--- a/torchquantum/datasets/vqe.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from torchpack.datasets.dataset import Dataset
-
-
-__all__ = ["VQE"]
-
-
-class VQEDataset:
-    def __init__(self, split, steps_per_epoch):
-        self.split = split
-        self.steps_per_epoch = steps_per_epoch
-
-    def __getitem__(self, index: int):
-        instance = {"input": -1, "target": -1}
-
-        return instance
-
-    def __len__(self) -> int:
-        if self.split == "train":
-            return self.steps_per_epoch
-        else:
-            return 1
-
-
-class VQE(Dataset):
-    def __init__(self, steps_per_epoch):
-        super().__init__(
-            {
-                split: VQEDataset(split=split, steps_per_epoch=steps_per_epoch)
-                for split in ["train", "valid", "test"]
-            }
-        )
diff --git a/torchquantum/density.py b/torchquantum/density.py
deleted file mode 100644
index 3ab865a4..00000000
--- a/torchquantum/density.py
+++ /dev/null
@@ -1,818 +0,0 @@
-import imp
-import torch
-import torch.nn as nn
-import numpy as np
-import functools
-import torchquantum.functional as tqf
-import torchquantum.Dfunc as dfunc
-import torchquantum as tq
-import copy
-from torchquantum.states import QuantumState
-from torchquantum.macro import C_DTYPE, ABC, ABC_ARRAY, INV_SQRT2
-from typing import Union, List, Iterable
-
-
-__all__ = ["DensityMatrix"]
-
-
-class DensityMatrix(nn.Module):
-    def __init__(self, n_wires: int, bsz: int = 1):
-        """Init function for DensityMatrix class(Density Operator)
-        Args:
-            n_wires (int): how many qubits for the densityMatrix.
-        """
-        super().__init__()
-
-        self.n_wires = n_wires
-        """
-        For example, when n_wires=3
-        matrix[001110] denotes the index of |001><110|=|index1><index2|
-        Set Initial value the density matrix of the pure state |00...00>
-        """
-        _matrix = torch.zeros(2 ** (2 * self.n_wires), dtype=C_DTYPE)
-        _matrix[0] = 1 + 0j
-        _matrix = torch.reshape(_matrix, [2] * (2 * self.n_wires))
-        self.register_buffer("matrix", _matrix)
-
-        repeat_times = [bsz] + [1] * len(self.matrix.shape)
-        self._matrix = self.matrix.repeat(*repeat_times)
-        self.register_buffer("matrix", self._matrix)
-
-        """
-        Whether or not calculate by states
-        """
-        self._calc_by_states = True
-
-        """
-        Remember whether or not a standard matrix on a given wire is contructed
-        """
-        self.construct = {}
-        for key in tqf.func_name_dict.keys():
-            self.construct[key] = [False] * n_wires
-
-        """
-        Store the constructed operator matrix
-        """
-        self.operator_matrix = {}
-        for key in tqf.func_name_dict.keys():
-            self.operator_matrix[key] = {}
-
-        """
-        Preserve the probability of all pure states. has the form [(p1,s1),(p2,s2),(p3,s3),...]
-              2**n 2**n 2**n
-         Matrix  3 purestate
-        """
-        self.state_list = []
-        for i in range(0, bsz):
-            self.state_list.append((1, QuantumState(n_wires)))
-
-    def set_calc_by_states(self, val):
-        self._calc_by_states = val
-
-    def update_matrix_from_states(self):
-        """Update the density matrix value from all pure states"""
-        _matrix = torch.zeros(2 ** (2 * self.n_wires), dtype=C_DTYPE)
-        _matrix = torch.reshape(_matrix, [2**self.n_wires, 2**self.n_wires])
-        self.register_buffer("matrix", _matrix)
-        bsz = self.matrix.shape[0]
-        repeat_times = [bsz] + [1] * len(self.matrix.shape)
-        self._matrix = self.matrix.repeat(*repeat_times)
-        for i in range(0, bsz):
-            for p, state in self.state_list:
-                self._matrix[i] = self._matrix[i] + p * state.density_matrix()[0][:][:]
-        self.register_buffer("matrix", self._matrix)
-
-    def vector(self):
-        return torch.reshape(_matrix, [2 ** (2 * self.n_wires)])
-
-    def print_2d(self, index):
-        """Print the matrix value of matrix[index]"""
-        _matrix = torch.reshape(self._matrix[index], [2**self.n_wires] * 2)
-        print(_matrix)
-
-    def trace(self, index):
-        """Return the trace of the DensityMatrix of matrix[index]"""
-        return torch.trace(self._matrix[index])
-
-    def positive_semidefinite(self, index):
-        """Check whether the matrix is positive semidefinite by Sylvester's_criterion"""
-        return np.all(np.linalg.eigvals(self._matrix[index]) > 0)
-
-    def check_valid(self):
-        """Check whether the matrix has trace 1 and is positive semidefinite"""
-        for i in range(0, self._matrix.shape[0]):
-            if self.trace(i) != 1 or not self.positive_semidefinite(i):
-                return False
-        return True
-
-    def spectral(self, index):
-        """Return the spectral of the DensityMatrix"""
-        return list(np.linalg.eigvals(self._matrix[index]))
-
-    def tensor(self, other):
-        """Return self tensor other(Notice the order)
-        Args:
-            other (DensityMatrix: Another density matrix
-        """
-        self._matrix = torch.kron(self._matrix, other._matrix)
-
-    def expand(self, other):
-        """Return other tensor self(Notice the order)
-        Args:
-            other (DensityMatrix: Another density matrix
-        """
-        self._matrix = torch.kron(other._matrix, self._matrix)
-
-    def clone_matrix(self, existing_matrix: torch.Tensor):
-        self._matrix = existing_matrix.clone()
-
-    def set_matrix(self, matrix: Union[torch.tensor, List]):
-        matrix = torch.tensor(matrix, dtype=C_DTYPE).to(self.matrix.device)
-        bsz = matrix.shape[0]
-        self.matrix = torch.reshape(
-            matrix, [bsz] + [2 ** (2 * self.n_wires), 2 ** (2 * self.n_wires)]
-        )
-
-    def evolve(self, operator):
-        """Evolve the density matrix in batchmode
-        operator has size [2**(2*self.n_wires),2**(2*self.n_wires)]
-        """
-        """Convert the matrix to vector of shape [bsz,2**(2*self.n_wires)]
-           Return U rho U^\dagger
-        """
-        bsz = self.matrix.shape[0]
-        expand_shape = [bsz] + list(operator.shape)
-
-        new_matrix = operator.expand(expand_shape).bmm(
-            torch.reshape(self.matrix, [bsz, 2 ** (2 * self.n_wires)])
-        )
-        self.matrix = torch.reshape(
-            new_matrix, [bsz, 2**self.n_wires, 2**self.n_wires]
-        )
-
-    def expectation(self):
-        """Expectation of a measurement"""
-        return
-
-    def set_from_state(self, probs, states: Union[torch.Tensor, List]):
-        """Get the density matrix of a mixed state.
-        Args:
-          probs:List of probability of each state
-          states:List of state.
-        For example:
-          probs:[0.5,0.5],states:[|00>,|11>]
-        Then the corresponding matrix is: 0.5|00><00|+0.5|11><11|
-         0.5, 0, 0, 0
-         0  , 0, 0, 0
-         0  , 0, 0, 0
-         0 ,  0, 0, 0.5
-         self._matrix[00][00]=self._matrix[11][11]=0.5
-        """
-        for i in range(0, len(probs)):
-            self.state_list
-        _matrix = torch.zeros(2 ** (2 * self.n_wires), dtype=C_DTYPE)
-        _matrix = torch.reshape(_matrix, [2**self.n_wires, 2**self.n_wires])
-        for i in range(0, len(probs)):
-            row = torch.reshape(states[i], [2**self.n_wires, 1])
-            col = torch.reshape(states[i], [1, 2**self.n_wires])
-            _matrix = _matrix + probs[i] * torch.matmul(row, col)
-        self.matrix = torch.reshape(_matrix, [2] * (2 * self.n_wires))
-        return
-
-    def _add(self, other):
-        """Return self + other
-        Args:
-            other (complex): a complex number.
-        """
-        if not isinstance(other, DensityMatrix):
-            other = DensityMatrix(other)
-        if not self._matrix.shape == other._matrix.shape:
-            raise ("Two density matrix must have the same shape.")
-        ret = copy.copy(self)
-        ret._matrix = self.matrix + other._matrix
-        return ret
-
-    def _multiply(self, other):
-        """Return other * self.
-        Args:
-            other (complex): a complex number.
-        """
-        ret = copy.copy(self)
-        ret._matrix = other * self._matrix
-        return ret
-
-    def purity(self):
-        """Calculate the purity of the DensityMatrix defined as \gamma=tr(\rho^2)"""
-        return torch.trace(torch.matmul(self._matrix, self._matrix))
-
-    def partial_trace(self, dims: List[int]):
-        """Calculate the partial trace of given sub-dimension, return a new density_matrix
-        Args:
-            dims:The list of sub-dimension
-            For example, If we have 3 qubit, the matrix shape is (8,8),
-            We want to do partial trace to qubit 0,2, dims=[0,2].
-            First, the matrix should be reshped to (2,2,2,2,2,2)
-            then we call  np.einsum('ijiiqi->jq', reshaped_dm)
-        """
-        return False
-
-    @property
-    def name(self):
-        return self.__class__.__name__
-
-    def __repr__(self):
-        return f"Density Matrix"
-
-    def hadamard(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.hadamard(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def shadamard(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.shadamard(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def paulix(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.paulix(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def pauliy(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.pauliy(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def pauliz(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.pauliz(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def i(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.i(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def s(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.s(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def t(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.t(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def sx(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.sx(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def cnot(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.cnot(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def cz(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.cz(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def cy(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.cy(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def swap(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.swap(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def sswap(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.sswap(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def cswap(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.cswap(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def toffoli(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-        dfunc.toffoli(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def multicnot(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        dfunc.multicnot(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def multixcnot(
-        self,
-        wires: Union[List[int], int],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        dfunc.multixcnot(self, wires=wires, inverse=inverse, comp_method=comp_method)
-
-    def rx(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.rx(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def ry(
-        self,
-        wires: Union[List[int], int],
-        params: torch.Tensor,
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.ry(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def rz(
-        self,
-        wires: Union[List[int], int],
-        params: torch.Tensor,
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.rz(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def rxx(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.rxx(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def ryy(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.ryy(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def rzz(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.rzz(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def rzx(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.rzx(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def phaseshift(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.phaseshift(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def rot(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        if params.dim() == 1:
-            params = params.unsqueeze(0)
-
-        dfunc.rot(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def multirz(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.multirz(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def crx(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.crx(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def cry(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.cry(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def crz(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.crz(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def crot(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        if params.dim() == 1:
-            params = params.unsqueeze(0)
-
-        dfunc.crot(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def u1(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.u1(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def u2(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        if params.dim() == 1:
-            params = params.unsqueeze(0)
-
-        dfunc.u2(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def u3(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        if params.dim() == 1:
-            params = params.unsqueeze(0)
-
-        dfunc.u3(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def cu1(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        if params.dim() == 1:
-            params = params.unsqueeze(0)
-
-        dfunc.cu1(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def cu2(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        if params.dim() == 1:
-            params = params.unsqueeze(0)
-
-        dfunc.cu2(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def cu3(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        if params.dim() == 1:
-            params = params.unsqueeze(0)
-
-        dfunc.cu3(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def qubitunitary(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.tensor(params, dtype=C_DTYPE)
-        else:
-            params = torch.tensor([params], dtype=C_DTYPE)
-
-        dfunc.qubitunitary(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def qubitunitaryfast(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.tensor(params, dtype=C_DTYPE)
-        else:
-            params = torch.tensor([params], dtype=C_DTYPE)
-
-        dfunc.qubitunitaryfast(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def qubitunitarystrict(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.tensor(params, dtype=C_DTYPE)
-        else:
-            params = torch.tensor([params], dtype=C_DTYPE)
-
-        dfunc.qubitunitarystrict(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    def single_excitation(
-        self,
-        wires: Union[List[int], int],
-        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
-        inverse: bool = False,
-        comp_method: str = "bmm",
-    ):
-
-        if isinstance(params, Iterable):
-            params = torch.Tensor(params)
-        else:
-            params = torch.Tensor([params])
-
-        dfunc.single_excitation(
-            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
-        )
-
-    h = hadamard
-    sh = shadamard
-    x = paulix
-    y = pauliy
-    z = pauliz
-    xx = rxx
-    yy = ryy
-    zz = rzz
-    zx = rzx
-    cx = cnot
-    ccnot = toffoli
-    ccx = toffoli
-    u = u3
-    cu = cu3
-    p = phaseshift
-    cp = cu1
-    cr = cu1
-    cphase = cu
diff --git a/torchquantum/density/__init__.py b/torchquantum/density/__init__.py
new file mode 100644
index 00000000..2e9c570a
--- /dev/null
+++ b/torchquantum/density/__init__.py
@@ -0,0 +1,26 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .density_mat import *
+from .density_func import *
diff --git a/torchquantum/densityfunc.py b/torchquantum/density/density_func.py
similarity index 97%
rename from torchquantum/densityfunc.py
rename to torchquantum/density/density_func.py
index 2d1d3a85..eae37063 100644
--- a/torchquantum/densityfunc.py
+++ b/torchquantum/density/density_func.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import functools
 import torch
 import numpy as np
@@ -5,9 +29,9 @@
 
 from typing import Callable, Union, Optional, List, Dict
 from .macro import C_DTYPE, ABC, ABC_ARRAY, INV_SQRT2
-from .utils import pauli_eigs, diag
+from .util.utils import pauli_eigs, diag
 from torchpack.utils.logging import logger
-from torchquantum.utils import normalize_statevector
+from torchquantum.util import normalize_statevector
 
 __all__ = [
     "func_name_dict",
@@ -90,6 +114,7 @@ def apply_unitary_density_einsum(density, mat, wires):
     Returns:
         torch.Tensor: The new statevector.
     """
+    
     device_wires = wires
     n_qubit = int((density.dim() - 1) / 2)
 
@@ -210,6 +235,7 @@ def apply_unitary_density_bmm(density, mat, wires):
     Returns:
         torch.Tensor: The new statevector.
     """
+    
     device_wires = wires
     n_qubit = int((density.dim() - 1) / 2)
 
@@ -299,8 +325,8 @@ def gate_wrapper(
 
     Returns:
         None.
-
     """
+    
     if params is not None:
         if not isinstance(params, torch.Tensor):
             # this is for qubitunitary gate
@@ -360,8 +386,28 @@ def gate_wrapper(
             q_device.states = apply_unitary_density_bmm(state, matrix, wires)
 
 
-def reset(q_device: tq.QuantumDevice, wires, inverse=False):
-    # reset the target qubits to 0, non-unitary operation
+def reset(q_device: tq.QuantumDevice, wires, inverse=False) -> None:
+    """Reset the target qubits to the state 0. It is a non-unitary operation.
+
+    Args:
+        q_device (tq.QuantumDevice): The quantum device.
+        wires (int or list): The target wire(s) to reset.
+        inverse (bool, optional): If True, performs an inverse reset operation. 
+            Defaults to False.
+
+    Returns:
+        None.
+
+    Examples:
+        >>> device = tq.QuantumDevice(n_wires=3)
+        >>> reset(device, wires=1)
+        >>> print(device.states)
+        [1., 0., 1., 0., 0., 0., 0., 0.]
+
+        >>> reset(device, wires=[0, 2])
+        >>> print(device.states)
+        [0., 0., 0., 0., 0., 0., 0., 0.]
+    """
     state = q_device.states
 
     wires = [wires] if isinstance(wires, int) else wires
@@ -394,8 +440,8 @@ def rx_matrix(params: torch.Tensor) -> torch.Tensor:
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
     """
     Seems to be a pytorch bug. Have to explicitly cast the theta to a
@@ -406,8 +452,8 @@ def rx_matrix(params: torch.Tensor) -> torch.Tensor:
     (input_is_complex == grad_is_complex) to be true, but got false.
     (Could this error message be improved?
     If so, please report an enhancement request to PyTorch.)
-
     """
+    
     co = torch.cos(theta / 2)
     jsi = 1j * torch.sin(-theta / 2)
 
@@ -424,8 +470,8 @@ def ry_matrix(params: torch.Tensor) -> torch.Tensor:
 
     Returns:
         The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
 
     co = torch.cos(theta / 2)
@@ -444,8 +490,8 @@ def rz_matrix(params: torch.Tensor) -> torch.Tensor:
 
     Returns:
         The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
     exp = torch.exp(-0.5j * theta)
 
@@ -461,6 +507,23 @@ def rz_matrix(params: torch.Tensor) -> torch.Tensor:
 
 
 def phaseshift_matrix(params):
+    """Compute the phase shift matrix.
+
+    Args:
+        params (torch.Tensor): Input parameters.
+
+    Returns:
+        torch.Tensor: The phase shift matrix.
+
+    Examples:
+        >>> params = torch.tensor([0.5])
+        >>> matrix = phaseshift_matrix(params)
+        >>> print(matrix)
+
+        >>> params = torch.tensor([1.0, 2.0, 3.0])
+        >>> matrix = phaseshift_matrix(params)
+        >>> print(matrix)
+    """
     phi = params.type(C_DTYPE)
     exp = torch.exp(1j * phi)
 
@@ -487,8 +550,8 @@ def rot_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     phi = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
     theta = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
     omega = params[:, 2].unsqueeze(dim=-1).type(C_DTYPE)
@@ -525,8 +588,8 @@ def multirz_eigvals(params, n_wires):
 
     Returns:
         torch.Tensor: The computed eigenvalues.
-
     """
+    
     theta = params.type(C_DTYPE)
     return torch.exp(
         -1j * theta / 2 * torch.tensor(pauli_eigs(n_wires)).to(params.device)
@@ -541,8 +604,8 @@ def multirz_matrix(params, n_wires):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     # torch diagonal not available for complex number
     eigvals = multirz_eigvals(params, n_wires)
     dia = diag(eigvals)
@@ -557,7 +620,6 @@ def rxx_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
 
     theta = params.type(C_DTYPE)
@@ -595,8 +657,8 @@ def ryy_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
     co = torch.cos(theta / 2)
     jsi = 1j * torch.sin(theta / 2)
@@ -632,8 +694,8 @@ def rzz_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
     exp = torch.exp(-0.5j * theta)
     conj_exp = torch.conj(exp)
@@ -664,8 +726,8 @@ def rzx_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
     co = torch.cos(theta / 2)
     jsi = 1j * torch.sin(theta / 2)
@@ -703,8 +765,8 @@ def crx_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+
     theta = params.type(C_DTYPE)
     co = torch.cos(theta / 2)
     jsi = 1j * torch.sin(-theta / 2)
@@ -734,8 +796,8 @@ def cry_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
     co = torch.cos(theta / 2)
     si = torch.sin(theta / 2)
@@ -765,8 +827,8 @@ def crz_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
     exp = torch.exp(-0.5j * theta)
 
@@ -793,8 +855,8 @@ def crot_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     phi = params[:, 0].type(C_DTYPE)
     theta = params[:, 1].type(C_DTYPE)
     omega = params[:, 2].type(C_DTYPE)
@@ -828,8 +890,8 @@ def u1_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     phi = params.type(C_DTYPE)
     exp = torch.exp(1j * phi)
 
@@ -856,8 +918,8 @@ def cu1_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     phi = params.type(C_DTYPE)
     exp = torch.exp(1j * phi)
 
@@ -884,8 +946,8 @@ def u2_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     phi = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
     lam = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
 
@@ -909,8 +971,8 @@ def cu2_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     phi = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
     lam = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
 
@@ -939,8 +1001,8 @@ def u3_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
     phi = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
     lam = params[:, 2].unsqueeze(dim=-1).type(C_DTYPE)
@@ -967,8 +1029,8 @@ def cu3_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
     phi = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
     lam = params[:, 2].unsqueeze(dim=-1).type(C_DTYPE)
@@ -1002,8 +1064,11 @@ def qubitunitary_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
+        
+    Raises:
+        AssertionError: If Operator is other than square matrix
     """
+    
     matrix = params.squeeze(0)
     try:
         assert matrix.shape[-1] == matrix.shape[-2]
@@ -1042,8 +1107,8 @@ def qubitunitaryfast_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     return params.squeeze(0)
 
 
@@ -1056,8 +1121,8 @@ def qubitunitarystrict_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     params.squeeze(0)
     mat = params
     U, Sigma, V = torch.svd(mat)
@@ -1072,8 +1137,8 @@ def multicnot_matrix(n_wires):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     mat = torch.eye(2**n_wires, dtype=C_DTYPE)
     mat[-1][-1] = 0
     mat[-2][-2] = 0
@@ -1091,8 +1156,8 @@ def multixcnot_matrix(n_wires):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     # when all control qubits are zero, then the target qubit will flip
     mat = torch.eye(2**n_wires, dtype=C_DTYPE)
     mat[0][0] = 0
@@ -1111,8 +1176,8 @@ def single_excitation_matrix(params):
 
     Returns:
         torch.Tensor: The computed unitary matrix.
-
     """
+    
     theta = params.type(C_DTYPE)
     co = torch.cos(theta / 2)
     si = torch.sin(theta / 2)
@@ -1258,8 +1323,8 @@ def hadamard(
 
     Returns:
         None.
-
     """
+    
     name = "hadamard"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1305,8 +1370,8 @@ def shadamard(
 
     Returns:
         None.
-
     """
+    
     name = "shadamard"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1352,8 +1417,8 @@ def paulix(
 
     Returns:
         None.
-
     """
+    
     name = "paulix"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1399,8 +1464,8 @@ def pauliy(
 
     Returns:
         None.
-
     """
+    
     name = "pauliy"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1446,8 +1511,8 @@ def pauliz(
 
     Returns:
         None.
-
     """
+    
     name = "pauliz"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1493,8 +1558,8 @@ def i(
 
     Returns:
         None.
-
     """
+    
     name = "i"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1540,8 +1605,8 @@ def s(
 
     Returns:
         None.
-
     """
+    
     name = "s"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1587,8 +1652,8 @@ def t(
 
     Returns:
         None.
-
     """
+    
     name = "t"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1634,8 +1699,8 @@ def sx(
 
     Returns:
         None.
-
     """
+    
     name = "sx"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1681,8 +1746,8 @@ def cnot(
 
     Returns:
         None.
-
     """
+    
     name = "cnot"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1728,8 +1793,8 @@ def cz(
 
     Returns:
         None.
-
     """
+    
     name = "cz"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1775,8 +1840,8 @@ def cy(
 
     Returns:
         None.
-
     """
+    
     name = "cy"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1822,8 +1887,8 @@ def rx(
 
     Returns:
         None.
-
     """
+    
     name = "rx"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1869,8 +1934,8 @@ def ry(
 
     Returns:
         None.
-
     """
+    
     name = "ry"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1916,8 +1981,8 @@ def rz(
 
     Returns:
         None.
-
     """
+    
     name = "rz"
     mat = mat_dict[name]
     gate_wrapper(
@@ -1963,8 +2028,8 @@ def rxx(
 
     Returns:
         None.
-
     """
+    
     name = "rxx"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2010,8 +2075,8 @@ def ryy(
 
     Returns:
         None.
-
     """
+    
     name = "ryy"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2057,8 +2122,8 @@ def rzz(
 
     Returns:
         None.
-
     """
+    
     name = "rzz"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2104,8 +2169,8 @@ def rzx(
 
     Returns:
         None.
-
     """
+    
     name = "rzx"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2151,8 +2216,8 @@ def swap(
 
     Returns:
         None.
-
     """
+    
     name = "swap"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2198,8 +2263,8 @@ def sswap(
 
     Returns:
         None.
-
     """
+    
     name = "sswap"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2245,8 +2310,8 @@ def cswap(
 
     Returns:
         None.
-
     """
+    
     name = "cswap"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2292,8 +2357,8 @@ def toffoli(
 
     Returns:
         None.
-
     """
+    
     name = "toffoli"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2339,8 +2404,8 @@ def phaseshift(
 
     Returns:
         None.
-
     """
+    
     name = "phaseshift"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2386,8 +2451,8 @@ def rot(
 
     Returns:
         None.
-
     """
+    
     name = "rot"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2433,8 +2498,8 @@ def multirz(
 
     Returns:
         None.
-
     """
+    
     name = "multirz"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2480,8 +2545,8 @@ def crx(
 
     Returns:
         None.
-
     """
+    
     name = "crx"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2527,8 +2592,8 @@ def cry(
 
     Returns:
         None.
-
     """
+    
     name = "cry"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2574,8 +2639,8 @@ def crz(
 
     Returns:
         None.
-
     """
+    
     name = "crz"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2621,8 +2686,8 @@ def crot(
 
     Returns:
         None.
-
     """
+    
     name = "crot"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2668,8 +2733,8 @@ def u1(
 
     Returns:
         None.
-
     """
+    
     name = "u1"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2715,8 +2780,8 @@ def u2(
 
     Returns:
         None.
-
     """
+    
     name = "u2"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2762,8 +2827,8 @@ def u3(
 
     Returns:
         None.
-
     """
+    
     name = "u3"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2809,8 +2874,8 @@ def cu1(
 
     Returns:
         None.
-
     """
+    
     name = "cu1"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2856,8 +2921,8 @@ def cu2(
 
     Returns:
         None.
-
     """
+    
     name = "cu2"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2903,8 +2968,8 @@ def cu3(
 
     Returns:
         None.
-
     """
+    
     name = "cu3"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2950,8 +3015,8 @@ def qubitunitary(
 
     Returns:
         None.
-
     """
+    
     name = "qubitunitary"
     mat = mat_dict[name]
     gate_wrapper(
@@ -2997,8 +3062,8 @@ def qubitunitaryfast(
 
     Returns:
         None.
-
     """
+    
     name = "qubitunitaryfast"
     mat = mat_dict[name]
     gate_wrapper(
@@ -3044,8 +3109,8 @@ def qubitunitarystrict(
 
     Returns:
         None.
-
     """
+    
     name = "qubitunitarystrict"
     mat = mat_dict[name]
     gate_wrapper(
@@ -3091,8 +3156,8 @@ def multicnot(
 
     Returns:
         None.
-
     """
+    
     name = "multicnot"
     mat = mat_dict[name]
     gate_wrapper(
@@ -3138,8 +3203,8 @@ def multixcnot(
 
     Returns:
         None.
-
     """
+    
     name = "multixcnot"
     mat = mat_dict[name]
     gate_wrapper(
@@ -3185,8 +3250,8 @@ def single_excitation(
 
     Returns:
         None.
-
     """
+    
     name = "single_excitation"
     mat = mat_dict[name]
     gate_wrapper(
diff --git a/torchquantum/density/density_mat.py b/torchquantum/density/density_mat.py
new file mode 100644
index 00000000..b7e42244
--- /dev/null
+++ b/torchquantum/density/density_mat.py
@@ -0,0 +1,1979 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import imp
+import torch
+import torch.nn as nn
+import numpy as np
+import functools
+import torchquantum.functional as tqf
+import torchquantum.Dfunc as dfunc
+import torchquantum as tq
+import copy
+from torchquantum.states import QuantumState
+from torchquantum.macro import C_DTYPE, ABC, ABC_ARRAY, INV_SQRT2
+from typing import Union, List, Iterable
+
+
+__all__ = ["DensityMatrix"]
+
+
+class DensityMatrix(nn.Module):
+    def __init__(self, n_wires: int, bsz: int = 1):
+        """Init function for DensityMatrix class(Density Operator)
+        Args:
+            n_wires (int): how many qubits for the densityMatrix.
+        """
+        super().__init__()
+
+        self.n_wires = n_wires
+        """
+        For example, when n_wires=3
+        matrix[001110] denotes the index of |001><110|=|index1><index2|
+        Set Initial value the density matrix of the pure state |00...00>
+        """
+        _matrix = torch.zeros(2 ** (2 * self.n_wires), dtype=C_DTYPE)
+        _matrix[0] = 1 + 0j
+        _matrix = torch.reshape(_matrix, [2] * (2 * self.n_wires))
+        self.register_buffer("matrix", _matrix)
+
+        repeat_times = [bsz] + [1] * len(self.matrix.shape)
+        self._matrix = self.matrix.repeat(*repeat_times)
+        self.register_buffer("matrix", self._matrix)
+
+        """
+        Whether or not calculate by states
+        """
+        self._calc_by_states = True
+
+        """
+        Remember whether or not a standard matrix on a given wire is contructed
+        """
+        self.construct = {}
+        for key in tqf.func_name_dict.keys():
+            self.construct[key] = [False] * n_wires
+
+        """
+        Store the constructed operator matrix
+        """
+        self.operator_matrix = {}
+        for key in tqf.func_name_dict.keys():
+            self.operator_matrix[key] = {}
+
+        """
+        Preserve the probability of all pure states. has the form [(p1,s1),(p2,s2),(p3,s3),...]
+              2**n 2**n 2**n
+         Matrix  3 purestate
+        """
+        self.state_list = []
+        for i in range(0, bsz):
+            self.state_list.append((1, QuantumState(n_wires)))
+
+    def set_calc_by_states(self, val):
+        """Set the value of the `_calc_by_states` attribute.
+
+        This method sets the flag that determines whether calculations should be performed using individual pure states or the density matrix.
+
+        Args:
+            val (bool): The new value for the `_calc_by_states` attribute.
+
+        Returns:
+            None
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.set_calc_by_states(True)
+            >>> device.calc_by_states
+            True
+        """
+        
+        self._calc_by_states = val
+
+    def update_matrix_from_states(self):
+        """Update the density matrix value from all pure states.
+
+        This method updates the density matrix value based on all the pure states in the state list.
+
+        Returns:
+            None
+        """
+        
+        _matrix = torch.zeros(2 ** (2 * self.n_wires), dtype=C_DTYPE)
+        _matrix = torch.reshape(_matrix, [2**self.n_wires, 2**self.n_wires])
+        self.register_buffer("matrix", _matrix)
+        bsz = self.matrix.shape[0]
+        repeat_times = [bsz] + [1] * len(self.matrix.shape)
+        self._matrix = self.matrix.repeat(*repeat_times)
+        for i in range(0, bsz):
+            for p, state in self.state_list:
+                self._matrix[i] = self._matrix[i] + p * state.density_matrix()[0][:][:]
+        self.register_buffer("matrix", self._matrix)
+
+    def vector(self):
+        """Return the density matrix as a vector.
+
+        This method reshapes the density matrix `_matrix` into a vector representation.
+
+        Returns:
+            torch.Tensor: The density matrix as a vector.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.matrix = torch.tensor([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
+            >>> vector = device.vector()
+            >>> print(vector)
+            tensor([1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
+        """
+        
+        return torch.reshape(_matrix, [2 ** (2 * self.n_wires)])
+
+    def print_2d(self, index):
+        """Print the matrix value at the given index.
+
+        This method prints the matrix value of `matrix[index]`. It reshapes the value into a 2D matrix
+        using the `torch.reshape` function and then prints it.
+
+        Args:
+            index (int): The index of the matrix value to print.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.matrix = torch.tensor([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
+            >>> device.print_2d(1)
+            tensor([[0, 0],
+                    [0, 1]])
+
+        """
+        
+        _matrix = torch.reshape(self._matrix[index], [2**self.n_wires] * 2)
+        print(_matrix)
+
+    def trace(self, index):
+        """Calculate and return the trace of the density matrix at the given index.
+
+        This method calculates the trace of the density matrix stored in `matrix[index]`
+        using the `torch.trace` function and returns the result.
+
+        Args:
+            index (int): The index of the matrix value.
+
+        Returns:
+            float: The trace of the density matrix.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.matrix = torch.tensor([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
+            >>> device.trace(0)
+            tensor(2)
+        """
+        
+        return torch.trace(self._matrix[index])
+
+    def positive_semidefinite(self, index):
+        """Check whether the matrix is positive semidefinite by Sylvester's_criterion"""
+        return np.all(np.linalg.eigvals(self._matrix[index]) > 0)
+
+    def check_valid(self):
+        """Check whether the matrix has trace 1 and is positive semidefinite"""
+        for i in range(0, self._matrix.shape[0]):
+            if self.trace(i) != 1 or not self.positive_semidefinite(i):
+                return False
+        return True
+
+    def spectral(self, index):
+        """Return the spectral of the DensityMatrix"""
+        return list(np.linalg.eigvals(self._matrix[index]))
+
+    def tensor(self, other):
+        """Return self tensor other(Notice the order)
+        
+        Args:
+            other (DensityMatrix: Another density matrix
+        """
+        self._matrix = torch.kron(self._matrix, other._matrix)
+
+    def expand(self, other):
+        """Return other tensor self(Notice the order)
+        
+        Args:
+            other (DensityMatrix: Another density matrix
+        """
+        self._matrix = torch.kron(other._matrix, self._matrix)
+
+    def clone_matrix(self, existing_matrix: torch.Tensor):
+        self._matrix = existing_matrix.clone()
+
+    def set_matrix(self, matrix: Union[torch.tensor, List]):
+        """
+        """
+        
+        matrix = torch.tensor(matrix, dtype=C_DTYPE).to(self.matrix.device)
+        bsz = matrix.shape[0]
+        self.matrix = torch.reshape(
+            matrix, [bsz] + [2 ** (2 * self.n_wires), 2 ** (2 * self.n_wires)]
+        )
+
+    def evolve(self, operator):
+        """Evolve the density matrix in batchmode
+        operator has size [2**(2*self.n_wires),2**(2*self.n_wires)]
+        """
+        """Convert the matrix to vector of shape [bsz,2**(2*self.n_wires)]
+           Return U rho U^\dagger
+        """
+        bsz = self.matrix.shape[0]
+        expand_shape = [bsz] + list(operator.shape)
+
+        new_matrix = operator.expand(expand_shape).bmm(
+            torch.reshape(self.matrix, [bsz, 2 ** (2 * self.n_wires)])
+        )
+        self.matrix = torch.reshape(
+            new_matrix, [bsz, 2**self.n_wires, 2**self.n_wires]
+        )
+
+    def expectation(self):
+        """Expectation of a measurement"""
+        return
+
+    def set_from_state(self, probs, states: Union[torch.Tensor, List]):
+        """Get the density matrix of a mixed state.
+        
+        Args:
+          probs:List of probability of each state
+          states:List of state.
+          
+        Examples:
+          probs:[0.5,0.5],states:[|00>,|11>]
+        Then the corresponding matrix is: 0.5|00><00|+0.5|11><11|
+         0.5, 0, 0, 0
+         0  , 0, 0, 0
+         0  , 0, 0, 0
+         0 ,  0, 0, 0.5
+         self._matrix[00][00]=self._matrix[11][11]=0.5
+        """
+        
+        for i in range(0, len(probs)):
+            self.state_list
+        _matrix = torch.zeros(2 ** (2 * self.n_wires), dtype=C_DTYPE)
+        _matrix = torch.reshape(_matrix, [2**self.n_wires, 2**self.n_wires])
+        for i in range(0, len(probs)):
+            row = torch.reshape(states[i], [2**self.n_wires, 1])
+            col = torch.reshape(states[i], [1, 2**self.n_wires])
+            _matrix = _matrix + probs[i] * torch.matmul(row, col)
+        self.matrix = torch.reshape(_matrix, [2] * (2 * self.n_wires))
+        return
+
+    def _add(self, other):
+        """Return self + other
+        
+        Args:
+            other (complex): a complex number.
+        """
+        
+        if not isinstance(other, DensityMatrix):
+            other = DensityMatrix(other)
+        if not self._matrix.shape == other._matrix.shape:
+            raise ("Two density matrix must have the same shape.")
+        ret = copy.copy(self)
+        ret._matrix = self.matrix + other._matrix
+        return ret
+
+    def _multiply(self, other):
+        """Return other * self.
+        
+        Args:
+            other (complex): a complex number.
+        """
+        
+        ret = copy.copy(self)
+        ret._matrix = other * self._matrix
+        return ret
+
+    def purity(self):
+        """Calculate the purity of the DensityMatrix defined as \gamma=tr(\rho^2)"""
+        return torch.trace(torch.matmul(self._matrix, self._matrix))
+
+    def partial_trace(self, dims: List[int]):
+        """Calculate the partial trace of given sub-dimension, return a new density_matrix.
+        
+        Args:
+            dims:The list of sub-dimension
+            For example, If we have 3 qubit, the matrix shape is (8,8),
+            We want to do partial trace to qubit 0,2, dims=[0,2].
+            First, the matrix should be reshped to (2,2,2,2,2,2)
+            then we call  np.einsum('ijiiqi->jq', reshaped_dm)
+        """
+        
+        return False
+
+    @property
+    def name(self):
+        return self.__class__.__name__
+
+    def __repr__(self):
+        return f"Density Matrix"
+
+    def hadamard(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a Hadamard gate on the specified wires.
+
+        This method applies a Hadamard gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the Hadamard gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.hadamard(wires=[0, 1], inverse=False)
+        """
+        dfunc.hadamard(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def shadamard(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a SHadamard gate (square root of Hadamard gate) on the specified wires.
+
+        This method applies a SHadamard gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the SHadamard gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.shadamard(wires=[0, 1], inverse=False)
+        """
+        dfunc.shadamard(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def paulix(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a Pauli-X gate (also known as the NOT gate) on the specified wires.
+
+        This method applies a Pauli-X gate (NOT gate) on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the Pauli-X gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.paulix(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.paulix(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def pauliy(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a Pauli-Y gate on the specified wires.
+
+        This method applies a Pauli-Y gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the Pauli-Y gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.pauliy(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.pauliy(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def pauliz(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a Pauli-Z gate on the specified wires.
+
+        This method applies a Pauli-Z gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the Pauli-Z gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.pauliz(wires=[0, 1], inverse=False)
+        """
+        dfunc.pauliz(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def i(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply an identity gate on the specified wires.
+
+        This method applies an identity gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the identity gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.i(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.i(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def s(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply an S gate on the specified wires.
+
+        This method applies an S gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the S gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.s(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.s(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def t(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a T gate on the specified wires.
+
+        This method applies a T gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the T gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires. Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.t(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.t(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def sx(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a SX gate (square root of Pauli-X gate) on the specified wires.
+
+        This method applies a SX gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the SX gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.sx(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.sx(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def cnot(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a controlled-NOT (CNOT) gate on the specified wires.
+
+        This method applies a controlled-NOT gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the CNOT gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.cnot(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.cnot(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def cz(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a controlled-Z (CZ) gate on the specified wires.
+
+        This method applies a controlled-Z gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the CZ gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.cz(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.cz(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def cy(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a controlled-Y (CY) gate on the specified wires.
+
+        This method applies a controlled-Y gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the CY gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.cy(wires=[0, 1], inverse=False)
+        """
+        
+        dfunc.cy(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def swap(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a swap gate on the specified wires.
+
+        This method applies a swap gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the swap gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.swap(wires=[0, 1, 2], inverse=False)
+        """
+        
+        dfunc.swap(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def sswap(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a symmetric swap gate on the specified wires.
+
+        This method applies a symmetric swap gate on the specified wires of the quantum device.
+        The gate is applied to all the wires if the inverse flag is set to False.
+        If the inverse flag is set to True, the gate is applied to all the wires except the first one.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the symmetric swap gate.
+            inverse (bool, optional): If True, apply the gate to all the wires except the first one.
+                If False, apply the gate to all the wires.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.sswap(wires=[0, 1, 2], inverse=False)
+        """
+            
+        dfunc.sswap(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def cswap(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a controlled swap (Fredkin) gate on the specified wires.
+
+        This method applies a controlled swap (Fredkin) gate on the specified wires of the quantum device.
+        The gate is applied to all the wires except the control wire if the inverse flag is set to True.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the controlled swap gate.
+            inverse (bool, optional): If True, apply the gate as a swap gate
+                (i.e., swap the target wires if the control wire is ON).
+                If False, apply the gate as a controlled swap gate (Fredkin gate).
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.cswap(wires=[0, 1, 2], inverse=False)
+        """
+        
+        dfunc.cswap(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def toffoli(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        """Apply a Toffoli (CCNOT) gate on the specified wires.
+
+        This method applies a Toffoli (CCNOT) gate on the specified wires of the quantum device.
+        The gate is applied to all the wires except the control wires if the inverse flag is set to True.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the Toffoli gate.
+            inverse (bool, optional): If True, apply the gate as an X gate
+                (i.e., flip the target wire if both control wires are ON).
+                If False, apply the gate as a Toffoli gate.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.toffoli(wires=[0, 1, 2], inverse=False)
+        """
+        
+        dfunc.toffoli(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def multicnot(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a multi-qubit controlled-NOT (CNOT) gate on the specified wires.
+
+        This method applies a multi-qubit controlled-NOT (CNOT) gate on the specified wires of the quantum device.
+        The gate is applied to all the wires except the control wire(s) if the inverse flag is set to True.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the CNOT gate.
+            inverse (bool, optional): If True, apply the gate as a multi-qubit X gate
+                (i.e., flip all target wires except the control wire(s)).
+                If False, apply the gate as a multi-qubit CNOT gate.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.multicnot(wires=[0, 1, 2], inverse=False)
+        """
+        
+        dfunc.multicnot(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def multixcnot(
+        self,
+        wires: Union[List[int], int],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a multi-qubit X gate or CNOT gate on the specified wires.
+
+        This method applies a multi-qubit X gate or CNOT gate on the specified wires of the quantum device.
+        The gate is applied to all the wires except the control wire(s) if the inverse flag is set to True.
+        The computation method for applying the gate can be controlled using the comp_method parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the X or CNOT gate.
+            inverse (bool, optional): If True, apply the gate as a multi-qubit X gate
+                (i.e., flip all target wires except the control wire(s)).
+                If False, apply the gate as a multi-qubit CNOT gate.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.multixcnot(wires=[0, 1, 2], inverse=False)
+        """
+        
+        dfunc.multixcnot(self, wires=wires, inverse=inverse, comp_method=comp_method)
+
+    def rx(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a single-qubit Rx gate on the specified wires.
+
+        This method applies a single-qubit Rx gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` tensor. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the Rx gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the Rx gate. It can be a tensor, numpy array, or a list of floats or ints.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=1)
+            >>> params = torch.tensor(0.5)
+            >>> device.rx(wires=0, params=params)
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.rx(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def ry(
+        self,
+        wires: Union[List[int], int],
+        params: torch.Tensor,
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a single-qubit Ry gate on the specified wires.
+
+        This method applies a single-qubit Ry gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` tensor. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the Ry gate.
+            params (torch.Tensor): The parameters of the Ry gate. It should be a tensor.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=1)
+            >>> params = torch.tensor(0.5)
+            >>> device.ry(wires=0, params=params)
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.ry(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def rz(
+        self,
+        wires: Union[List[int], int],
+        params: torch.Tensor,
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a single-qubit Rz gate on the specified wires.
+
+        This method applies a single-qubit Rz gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` tensor. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the Rz gate.
+            params (torch.Tensor): The parameters of the Rz gate. It should be a tensor.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=1)
+            >>> params = torch.tensor(0.5)
+            >>> device.rz(wires=0, params=params)
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.rz(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def rxx(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a rotation XX gate on the specified wires.
+
+        This method applies a rotation XX gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the rotation XX gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the rotation XX gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.rxx(wires=[0, 1], params=0.1)
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.rxx(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def ryy(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a rotation YY gate on the specified wires.
+
+        This method applies a rotation YY gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the rotation YY gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the rotation YY gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.rzz(wires=[0, 1], params=0.1)
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.ryy(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def rzz(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a rotation ZZ gate on the specified wires.
+
+        This method applies a controlled ZZ gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the rotation ZZ gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the rotation ZZ gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.rzz(wires=[0, 1], params=0.3)
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.rzz(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def rzx(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a controlled Rz gate on the specified wires.
+
+        This method applies a controlled Rz gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the controlled Rz gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the controlled Rz gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.rzx(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.rzx(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def phaseshift(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a phase shift gate on the specified wires.
+
+        This method applies a phase shift gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the phase shift gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the phase shift gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.phaseshift(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.phaseshift(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def rot(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a rotation gate on the specified wires.
+
+        This method applies a rotation gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The wires on which to apply the rotation gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the rotation gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.rot(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        if params.dim() == 1:
+            params = params.unsqueeze(0)
+
+        dfunc.rot(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def multirz(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a multi-controlled Z-rotation gate on the specified control wires.
+
+        This method applies a multi-controlled Z-rotation gate on the specified control wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control wires on which to apply the multi-controlled Z-rotation gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the multi-controlled Z-rotation gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.multirz(wires=[0, 1], params=[0.1, 0.2])
+        """
+
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.multirz(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def crx(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a controlled X-rotation gate on the specified control and target wires.
+
+        This method applies a controlled X-rotation gate on the specified control and target wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the controlled X-rotation gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the controlled X-rotation gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.crx(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.crx(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def cry(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a controlled Y-rotation gate on the specified control and target wires.
+
+        This method applies a controlled Y-rotation gate on the specified control and target wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the controlled Y-rotation gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the controlled Y-rotation gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.cry(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.cry(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def crz(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a controlled phase rotation gate on the specified control and target wires.
+
+        This method applies a controlled phase rotation gate on the specified control and target wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the controlled phase rotation gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the controlled phase rotation gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.crz(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.crz(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def crot(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a controlled-rotation gate on the specified control and target wires.
+
+        This method applies a controlled-rotation gate on the specified control and target wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The control and target wires on which to apply the controlled-rotation gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the controlled-rotation gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.crot(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        if params.dim() == 1:
+            params = params.unsqueeze(0)
+
+        dfunc.crot(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def u1(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a u1 gate on the specified wires.
+
+        This method applies a u1 gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the u1 gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the u1 gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.u1(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.u1(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def u2(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a u2 gate on the specified wires.
+
+        This method applies a u2 gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the u2 gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the u2 gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.u2(wires=[0, 1], params=[0.1, 0.2])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        if params.dim() == 1:
+            params = params.unsqueeze(0)
+
+        dfunc.u2(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def u3(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a u3 gate on the specified wires.
+
+        This method applies a u3 gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the u3 gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the u3 gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.u3(wires=[0, 1], params=[0.1, 0.2, 0.3])
+
+        """
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        if params.dim() == 1:
+            params = params.unsqueeze(0)
+
+        dfunc.u3(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def cu1(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a controlled-u1 gate on the specified wires.
+
+        This method applies a controlled-u1 gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the controlled-u1 gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the controlled-u1 gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.cu1(wires=[0, 1], params=[0.3, 0.5])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        if params.dim() == 1:
+            params = params.unsqueeze(0)
+
+        dfunc.cu1(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def cu2(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a controlled-u2 gate on the specified wires.
+
+        This method applies a controlled-u2 gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the controlled-u2 gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the controlled-u2 gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=2)
+            >>> device.cu2(wires=[0, 1], params=[0.3, 0.5])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        if params.dim() == 1:
+            params = params.unsqueeze(0)
+
+        dfunc.cu2(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def cu3(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a controlled-u3 gate on the specified wires.
+
+        This method applies a controlled-u3 gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the controlled-u3 gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the controlled-u3 gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.cu3(wires=[0, 1], params=[0.5, 0.5, 0.5])
+
+        """
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        if params.dim() == 1:
+            params = params.unsqueeze(0)
+
+        dfunc.cu3(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def qubitunitary(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a unitary gate on the specified wires.
+
+        This method applies a unitary gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.qubitunitary(wires=[0, 1], params=[0.5, 0.5])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.tensor(params, dtype=C_DTYPE)
+        else:
+            params = torch.tensor([params], dtype=C_DTYPE)
+
+        dfunc.qubitunitary(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def qubitunitaryfast(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a unitary gate on the specified wires (fast method).
+
+        This method applies a unitary gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` flag to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter. This method uses a fast implementation
+        for applying the gate.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.qubitunitaryfast(wires=[0, 1], params=[0.5, 0.5])
+        """
+        
+        if isinstance(params, Iterable):
+            params = torch.tensor(params, dtype=C_DTYPE)
+        else:
+            params = torch.tensor([params], dtype=C_DTYPE)
+
+        dfunc.qubitunitaryfast(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def qubitunitarystrict(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+
+        """Apply a unitary gate on the specified wires.
+
+        This method applies a unitary gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` parameter to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.qubitunitarystrict(wires=[0, 1], params=[0.5, 0.5])
+
+        """
+        if isinstance(params, Iterable):
+            params = torch.tensor(params, dtype=C_DTYPE)
+        else:
+            params = torch.tensor([params], dtype=C_DTYPE)
+
+        dfunc.qubitunitarystrict(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    def single_excitation(
+        self,
+        wires: Union[List[int], int],
+        params: Union[torch.Tensor, np.ndarray, List[float], List[int], int, float],
+        inverse: bool = False,
+        comp_method: str = "bmm",
+    ):
+        
+        """Apply a single excitation gate on the specified wires.
+        
+        This method applies a single excitation gate on the specified wires of the quantum device.
+        The gate is parametrized by the given `params` values. The gate can be applied in the inverse
+        direction by setting the `inverse` parameter to True. The computation method for applying the gate
+        can be controlled using the `comp_method` parameter.
+
+        Args:
+            wires (Union[List[int], int]): The target wires on which to apply the gate.
+            params (Union[torch.Tensor, np.ndarray, List[float], List[int], int, float]):
+                The parameters of the gate. It can be a tensor or array-like object.
+                If a single value is provided, it will be broadcasted to all parameters.
+            inverse (bool, optional): If True, apply the gate in the inverse direction.
+                Defaults to False.
+            comp_method (str, optional): The computation method for applying the gate.
+                Supported options are "bmm" (batch matrix multiplication) and "einsum" (Einstein summation).
+                Defaults to "bmm".
+        
+        Returns:
+            None.
+
+        Examples:
+            >>> device = QuantumDevice(n_wires=3)
+            >>> device.single_excitation(wires=[0, 2], params=[0.1, 0.2])
+        """
+    
+        if isinstance(params, Iterable):
+            params = torch.Tensor(params)
+        else:
+            params = torch.Tensor([params])
+
+        dfunc.single_excitation(
+            self, wires=wires, params=params, inverse=inverse, comp_method=comp_method
+        )
+
+    h = hadamard
+    sh = shadamard
+    x = paulix
+    y = pauliy
+    z = pauliz
+    xx = rxx
+    yy = ryy
+    zz = rzz
+    zx = rzx
+    cx = cnot
+    ccnot = toffoli
+    ccx = toffoli
+    u = u3
+    cu = cu3
+    p = phaseshift
+    cp = cu1
+    cr = cu1
+    cphase = cu
diff --git a/torchquantum/device/__init__.py b/torchquantum/device/__init__.py
new file mode 100644
index 00000000..1fd5a939
--- /dev/null
+++ b/torchquantum/device/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .devices import *
\ No newline at end of file
diff --git a/torchquantum/devices.py b/torchquantum/device/devices.py
similarity index 72%
rename from torchquantum/devices.py
rename to torchquantum/device/devices.py
index bc34dcd0..c3f41cf1 100644
--- a/torchquantum/devices.py
+++ b/torchquantum/device/devices.py
@@ -1,9 +1,33 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn as nn
 import numpy as np
 
 from torchquantum.macro import C_DTYPE
-from torchquantum.functional import func_name_dict
+from torchquantum.functional import func_name_dict, func_name_dict_collect
 
 from typing import Union
 
@@ -50,6 +74,7 @@ def __init__(
         self.op_history = []
 
     def reset_op_history(self):
+        """Resets the all Operation of the quantum device"""
         self.op_history = []
 
     def clone_states(self, existing_states: torch.Tensor):
@@ -62,6 +87,7 @@ def set_states(self, states: torch.Tensor):
         self.states = torch.reshape(states, [bsz] + [2] * self.n_wires)
 
     def reset_states(self, bsz: int):
+        """Reset the States of the quantum device"""
         repeat_times = [bsz] + [1] * len(self.state.shape)
         self.states = self.state.repeat(*repeat_times).to(self.state.device)
 
@@ -100,8 +126,11 @@ def name(self):
         return self.__class__.__name__
 
     def __repr__(self):
-        return f" class: {self.name} \n device name: {self.device_name} \n number of qubits: {self.n_wires} \n batch size: {self.bsz} \n current computing device: {self.state.device} \n recording op history: {self.record_op} \n current states: {self.get_states_1d().cpu().detach().numpy()}"
+        return f" class: {self.name} \n device name: {self.device_name} \n number of qubits: {self.n_wires} \n batch size: {self.bsz} \n current computing device: {self.state.device} \n recording op history: {self.record_op} \n current states: {repr(self.get_states_1d().cpu().detach().numpy())}"
 
 
 for func_name, func in func_name_dict.items():
     setattr(QuantumDevice, func_name, func)
+
+for func_name, func in func_name_dict_collect.items():
+    setattr(QuantumDevice, func_name, func)
diff --git a/torchquantum/encoding/__init__.py b/torchquantum/encoding/__init__.py
new file mode 100644
index 00000000..202d6d70
--- /dev/null
+++ b/torchquantum/encoding/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .encodings import *
diff --git a/torchquantum/encoding.py b/torchquantum/encoding/encodings.py
similarity index 92%
rename from torchquantum/encoding.py
rename to torchquantum/encoding/encodings.py
index a1758350..e519181b 100644
--- a/torchquantum/encoding.py
+++ b/torchquantum/encoding/encodings.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torchquantum as tq
 
@@ -9,6 +33,12 @@
 
 
 class Encoder(tq.QuantumModule):
+    """Encodes the given classic state to quantum state.
+
+    Methods:
+        - forward(qdev: tq.QuantumDevice, x): Performs the encoding using a quantum device.
+
+    """
     def __init__(self):
         super().__init__()
         pass
@@ -101,12 +131,25 @@ def to_qiskit(self, n_wires, x):
 
 
 class PhaseEncoder(Encoder, metaclass=ABCMeta):
+    """PhaseEncoder is a subclass of Encoder and represents a phase encoder.
+    It applies a specified quantum function to encode input data using a quantum device."""
     def __init__(self, func):
         super().__init__()
         self.func = func
 
     @tq.static_support
     def forward(self, qdev: tq.QuantumDevice, x):
+        """
+                Performs the encoding using a quantum device.
+
+                Args:
+                    qdev (tq.QuantumDevice): The quantum device to be used for encoding.
+                    x (torch.Tensor): The input data to be encoded.
+
+                Returns:
+                    torch.Tensor: The encoded data.
+
+                """
         for k in range(qdev.n_wires):
             self.func(
                 qdev,
@@ -118,6 +161,8 @@ def forward(self, qdev: tq.QuantumDevice, x):
 
 
 class MultiPhaseEncoder(Encoder, metaclass=ABCMeta):
+    """PhaseEncoder is a subclass of Encoder and represents a phase encoder.
+    It applies a specified quantum function to encode input data using a quantum device."""
     def __init__(self, funcs, wires=None):
         super().__init__()
         self.funcs = funcs if isinstance(funcs, Iterable) else [funcs]
@@ -125,6 +170,17 @@ def __init__(self, funcs, wires=None):
 
     @tq.static_support
     def forward(self, qdev: tq.QuantumDevice, x):
+        """
+                Performs the encoding using a quantum device.
+
+                Args:
+                    qdev (tq.QuantumDevice): The quantum device to be used for encoding.
+                    x (torch.Tensor): The input data to be encoded.
+
+                Returns:
+                    torch.Tensor: The encoded data.
+
+                """
         if self.wires is None:
             self.wires = list(range(qdev.n_wires)) * (len(self.funcs) // qdev.n_wires)
 
@@ -150,10 +206,22 @@ def forward(self, qdev: tq.QuantumDevice, x):
 
 
 class StateEncoder(Encoder, metaclass=ABCMeta):
+    """StateEncoder is a subclass of Encoder and represents a state encoder.
+    It encodes the input data into the state vector of a quantum device."""
     def __init__(self):
         super().__init__()
 
     def forward(self, qdev: tq.QuantumDevice, x):
+        """
+            Performs the encoding by preparing the state vector of the quantum device.
+
+                Args:
+                    qdev (tq.QuantumDevice): The quantum device to be used for encoding.
+                    x (torch.Tensor): The input data to be encoded.
+                Returns:
+                    torch.Tensor: The encoded data.
+
+                """
         # encoder the x to the statevector of the quantum device
 
         # normalize the input
@@ -173,6 +241,8 @@ def forward(self, qdev: tq.QuantumDevice, x):
 
 
 class MagnitudeEncoder(Encoder, metaclass=ABCMeta):
+    """MagnitudeEncoder is a subclass of Encoder and represents a magnitude encoder.
+    It encodes the input data by considering the magnitudes of the elements."""
     def __init__(self):
         super().__init__()
 
diff --git a/torchquantum/functional/__init__.py b/torchquantum/functional/__init__.py
new file mode 100644
index 00000000..aefad506
--- /dev/null
+++ b/torchquantum/functional/__init__.py
@@ -0,0 +1,33 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .functionals import *
+
+from .func_mat_exp import *
+from .func_controlled_unitary import *
+
+func_name_dict_collect = {
+    'matrix_exp': matrix_exp,
+    'controlled_unitary': controlled_unitary,
+}
diff --git a/torchquantum/functional/func_controlled_unitary.py b/torchquantum/functional/func_controlled_unitary.py
new file mode 100644
index 00000000..6d476fc3
--- /dev/null
+++ b/torchquantum/functional/func_controlled_unitary.py
@@ -0,0 +1,132 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import numpy as np
+import torch
+from torchquantum.functional.functionals import gate_wrapper
+from torchquantum.macro import *
+
+def controlled_unitary(
+    qdev,
+    c_wires,
+    t_wires,
+    params,
+):
+    """Create a controlled operation from a given operation.
+
+    Args:
+        op: the operation
+        c_wires: controlled wires, will only be a set such as 1, [2,3]
+        t_wires: can be a list of list of wires, multiple sets
+        [[1,2], [3,4]]
+        params: the parameters of the unitary
+    
+    Returns:
+        None.
+
+    """
+    if isinstance(params, np.ndarray):
+        params = torch.from_numpy(params)
+
+    c_wires = np.array(c_wires)
+    t_wires = np.array(t_wires)
+    # self.n_t_wires = op.n_wires
+    # assert len(t_wires) == op.n_wires
+
+    orig_u = params
+
+    orig_u_n_wires = int(np.log2(orig_u.shape[-1]))
+
+    wires = []
+
+    if c_wires.ndim == 0:
+        # only one control qubit
+        # 1
+        n_c_wires = 1
+        wires.append(c_wires.item())
+    elif c_wires.ndim == 1:
+        # multiple control qubits
+        # [1, 2]
+        n_c_wires = c_wires.shape[0]
+        wires.extend(list(c_wires))
+
+    if t_wires.ndim == 0:
+        # single qubit U on one set
+        # 2
+        n_t_wires = 1
+        n_set_t_wires = 1
+        wires.append(t_wires.item())
+    elif t_wires.ndim == 1:
+        # single qubit U on multiple sets
+        # [1, 2, 3]
+        # or multi qubit U on one set
+        # [2, 3]
+        n_t_wires = t_wires.shape[0]
+        n_set_t_wires = n_t_wires // orig_u_n_wires
+        wires.extend(list(t_wires.flatten()))
+
+    elif t_wires.ndim == 2:
+        # multi qubit unitary on multiple sets
+        # [[2, 3], [4, 5]]
+        n_t_wires = t_wires.flatten().shape[0]
+        n_set_t_wires = n_t_wires // orig_u_n_wires
+        wires.extend(list(t_wires.flatten()))
+
+    n_wires = n_c_wires + n_t_wires
+
+    # compute the new unitary, then permute
+    unitary = torch.tensor(torch.zeros(2**n_wires, 2**n_wires, dtype=C_DTYPE))
+    for k in range(2**n_wires - 2**n_t_wires):
+        unitary[k, k] = 1.0 + 0.0j
+
+    # compute kronecker product of all the controlled target
+
+    controlled_u = None
+    for k in range(n_set_t_wires):
+        if controlled_u is None:
+            controlled_u = orig_u
+        else:
+            controlled_u = torch.kron(controlled_u, orig_u)
+
+    d_controlled_u = controlled_u.shape[-1]
+    unitary[-d_controlled_u:, -d_controlled_u:] = controlled_u
+
+    # return cls(
+        # has_params=True,
+        # trainable=trainable,
+        # init_params=unitary,
+        # n_wires=n_wires,
+        # wires=wires,
+    # )
+
+    name = 'qubitunitaryfast'
+    unitary = unitary.to(qdev.device)
+    gate_wrapper(
+        name=name,
+        mat=unitary,
+        method='bmm',
+        q_device=qdev,
+        wires=wires,
+        n_wires=n_wires,
+    )
diff --git a/torchquantum/functional/func_mat_exp.py b/torchquantum/functional/func_mat_exp.py
new file mode 100644
index 00000000..d8f603e4
--- /dev/null
+++ b/torchquantum/functional/func_mat_exp.py
@@ -0,0 +1,71 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+from .functionals import gate_wrapper
+from typing import Union
+import numpy as np
+import torchquantum.functional as tqf
+
+__all__ = ["matrix_exp"]
+
+def matrix_exp(
+    qdev,
+    wires,
+    params: Union[torch.Tensor, np.ndarray],
+    n_wires=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the matrix exponential operation.
+
+    Args:
+        qdev (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    if isinstance(params, np.ndarray):
+        params = torch.from_numpy(params)
+
+    mat = torch.matrix_exp(params)
+
+    name = 'qubitunitaryfast'
+
+    tqf.qubitunitaryfast(
+        q_device=qdev,
+        wires=wires,
+        params=mat,
+    )
diff --git a/torchquantum/functional.py b/torchquantum/functional/functionals.py
similarity index 69%
rename from torchquantum/functional.py
rename to torchquantum/functional/functionals.py
index 94c77074..d459cdb8 100644
--- a/torchquantum/functional.py
+++ b/torchquantum/functional/functionals.py
@@ -1,17 +1,39 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import functools
 import torch
 import numpy as np
 
-import torchquantum as tq
-
 from typing import Callable, Union, Optional, List, Dict, TYPE_CHECKING
-from .macro import C_DTYPE, F_DTYPE, ABC, ABC_ARRAY, INV_SQRT2
-from .utils import pauli_eigs, diag
+from ..macro import C_DTYPE, F_DTYPE, ABC, ABC_ARRAY, INV_SQRT2
+from ..util.utils import pauli_eigs, diag
 from torchpack.utils.logging import logger
-from torchquantum.utils import normalize_statevector
+from torchquantum.util import normalize_statevector
 
 if TYPE_CHECKING:
-    from torchquantum.devices import QuantumDevice
+    from torchquantum.device import QuantumDevice
 else:
     QuantumDevice = None
 
@@ -55,6 +77,7 @@
     "u1",
     "u2",
     "u3",
+    "cu",
     "cu1",
     "cu2",
     "cu3",
@@ -83,6 +106,27 @@
     "reset",
     "ecr",
     "echoedcrossresonance",
+    "qft",
+    "sdg",
+    "iswap",
+    "cs",
+    "csdg",
+    "csx",
+    "chadamard",
+    "ccz",
+    "dcx",
+    "xxminyy",
+    "xxplusyy",
+    "c3x",
+    "tdg",
+    "sxdg",
+    "ch",
+    "r",
+    "c4x",
+    "rccx",
+    "rc3x",
+    "globalphase",
+    "c3sx",
 ]
 
 
@@ -272,7 +316,9 @@ def gate_wrapper(
             {
                 "name": name,  # type: ignore
                 "wires": np.array(wires).squeeze().tolist(),
-                "params": params.squeeze().detach().cpu().numpy().tolist() if params is not None else None,
+                "params": params.squeeze().detach().cpu().numpy().tolist()
+                if params is not None
+                else None,
                 "inverse": inverse,
                 "trainable": params.requires_grad if params is not None else False,
             }
@@ -298,7 +344,7 @@ def gate_wrapper(
                 "qubitunitarystrict",
             ]:
                 matrix = mat(params)
-            elif name in ["multicnot", "multixcnot"]:
+            elif name in ["multicnot", "multixcnot", "qft"]:
                 # this is for gates that can be applied to arbitrary numbers of
                 # qubits but no params, such as multicnot
                 matrix = mat(n_wires)
@@ -427,6 +473,15 @@ def rz_matrix(params: torch.Tensor) -> torch.Tensor:
 
 
 def phaseshift_matrix(params):
+    """Compute unitary matrix for phaseshift gate.
+
+    Args:
+        params (torch.Tensor): The rotation angle.
+
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+
+    """
     phi = params.type(C_DTYPE)
     exp = torch.exp(1j * phi)
 
@@ -483,6 +538,124 @@ def rot_matrix(params):
     ).squeeze(0)
 
 
+def xxminyy_matrix(params):
+    """Compute unitary matrix for XXminusYY gate.
+
+    Args:
+        params (torch.Tensor): The rotation angle. (Theta,Beta)
+
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+
+    """
+    theta = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
+    beta = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
+
+    co = torch.cos(theta / 2)
+    si = torch.sin(theta / 2)
+
+    return torch.stack(
+        [
+            torch.cat(
+                [
+                    co,
+                    torch.tensor([[0]]),
+                    torch.tensor([[0]]),
+                    (-1j * si * torch.exp(-1j * beta)),
+                ],
+                dim=-1,
+            ),
+            torch.cat(
+                [
+                    torch.tensor([[0]]),
+                    torch.tensor([[1]]),
+                    torch.tensor([[0]]),
+                    torch.tensor([[0]]),
+                ],
+                dim=-1,
+            ),
+            torch.cat(
+                [
+                    torch.tensor([[0]]),
+                    torch.tensor([[0]]),
+                    torch.tensor([[1]]),
+                    torch.tensor([[0]]),
+                ],
+                dim=-1,
+            ),
+            torch.cat(
+                [
+                    (-1j * si * torch.exp(1j * beta)),
+                    torch.tensor([[0]]),
+                    torch.tensor([[0]]),
+                    co,
+                ],
+                dim=-1,
+            ),
+        ],
+        dim=-2,
+    ).squeeze(0)
+
+
+def xxplusyy_matrix(params):
+    """Compute unitary matrix for XXplusYY gate.
+
+    Args:
+        params (torch.Tensor): The rotation angle. (Theta,Beta)
+
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+
+    """
+    theta = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
+    beta = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
+
+    co = torch.cos(theta / 2)
+    si = torch.sin(theta / 2)
+
+    return torch.stack(
+        [
+            torch.cat(
+                [
+                    torch.tensor([[1]]),
+                    torch.tensor([[0]]),
+                    torch.tensor([[0]]),
+                    torch.tensor([[0]]),
+                ],
+                dim=-1,
+            ),
+            torch.cat(
+                [
+                    torch.tensor([[0]]),
+                    co,
+                    (-1j * si * torch.exp(1j * beta)),
+                    torch.tensor([[0]]),
+                ],
+                dim=-1,
+            ),
+            torch.cat(
+                [
+                    torch.tensor([[0]]),
+                    (-1j * si * torch.exp(-1j * beta)),
+                    co,
+                    torch.tensor([[0]]),
+                ],
+                dim=-1,
+            ),
+            torch.cat(
+                [
+                    torch.tensor([[0]]),
+                    torch.tensor([[0]]),
+                    torch.tensor([[0]]),
+                    torch.tensor([[1]]),
+                ],
+                dim=-1,
+            ),
+        ],
+        dim=-2,
+    ).squeeze(0)
+
+
 def multirz_eigvals(params, n_wires):
     """Compute eigenvalue for multiqubit RZ gate.
 
@@ -814,6 +987,39 @@ def u1_matrix(params):
     ).squeeze(0)
 
 
+def cu_matrix(params):
+    """Compute unitary matrix for CU gate.
+    Args:
+        params (torch.Tensor): The rotation angle.
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+    """
+    theta = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
+    phi = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
+    lam = params[:, 2].unsqueeze(dim=-1).type(C_DTYPE)
+    gamma = params[:, 3].unsqueeze(dim=-1).type(C_DTYPE)
+
+    co = torch.cos(theta / 2)
+    si = torch.sin(theta / 2)
+
+    matrix = (
+        torch.tensor(
+            [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]],
+            dtype=C_DTYPE,
+            device=params.device,
+        )
+        .unsqueeze(0)
+        .repeat(phi.shape[0], 1, 1)
+    )
+
+    matrix[:, 2, 2] = co * torch.exp(1j * gamma)
+    matrix[:, 2, 3] = -si * torch.exp(1j * (lam + gamma))
+    matrix[:, 3, 2] = si * torch.exp(1j * (phi + gamma))
+    matrix[:, 3, 3] = co * torch.exp(1j * (phi + lam + gamma))
+
+    return matrix.squeeze(0)
+
+
 def cu1_matrix(params):
     """Compute unitary matrix for CU1 gate.
 
@@ -1101,6 +1307,123 @@ def singleexcitation_matrix(params):
     return matrix.squeeze(0)
 
 
+def qft_matrix(n_wires):
+    """Compute unitary matrix for QFT.
+
+    Args:
+        n_wires: the number of qubits
+    """
+    dimension = 2**n_wires
+    mat = torch.zeros((dimension, dimension), dtype=torch.complex64)
+    omega = np.exp(2 * np.pi * 1j / dimension)
+
+    for m in range(dimension):
+        for n in range(dimension):
+            mat[m, n] = omega ** (m * n)
+    mat = mat / np.sqrt(dimension)
+    return mat
+
+
+def r_matrix(params: torch.Tensor) -> torch.Tensor:
+    """Compute unitary matrix for R gate.
+
+    Args:
+        params (torch.Tensor): The rotation angle.
+
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+
+    """
+
+    theta = params[:, 0].unsqueeze(dim=-1).type(C_DTYPE)
+    phi = params[:, 1].unsqueeze(dim=-1).type(C_DTYPE)
+    exp = torch.exp(-1j * phi)
+    """
+    Seems to be a pytorch bug. Have to explicitly cast the theta to a
+    complex number. If directly theta = params, then get error:
+
+    allow_unreachable=True, accumulate_grad=True)  # allow_unreachable flag
+    RuntimeError: Expected isFloatingType(grad.scalar_type()) ||
+    (input_is_complex == grad_is_complex) to be true, but got false.
+    (Could this error message be improved?
+    If so, please report an enhancement request to PyTorch.)
+
+    """
+    co = torch.cos(theta / 2)
+    jsi = 1j * torch.sin(-theta / 2)
+
+    return torch.stack(
+        [
+            torch.cat([co, exp * jsi], dim=-1),
+            torch.cat([torch.conj(exp) * jsi, co], dim=-1),
+        ],
+        dim=-2,
+    ).squeeze(0)
+
+
+def globalphase_matrix(params):
+    """Compute unitary matrix for Multi qubit XCNOT gate.
+    Args:
+        params (torch.Tensor): The phase.
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+    """
+    phase = params.type(C_DTYPE)
+    exp = torch.exp(1j * phase)
+    matrix = torch.tensor([[exp]], dtype=C_DTYPE, device=params.device)
+
+    return matrix
+
+
+def c3x_matrix():
+    """Compute unitary matrix for C3X.
+    Args:
+        None
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+    """
+
+    mat = torch.eye(16, dtype=C_DTYPE)
+    mat[15][15] = 0
+    mat[14][14] = 0
+    mat[15][14] = 1
+    mat[14][15] = 1
+
+    return mat
+
+
+def c4x_matrix():
+    """Compute unitary matrix for C4X gate.
+    Args:
+        None
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+    """
+    mat = torch.eye(32, dtype=C_DTYPE)
+    mat[30][30] = 0
+    mat[30][31] = 1
+    mat[31][31] = 0
+    mat[31][30] = 1
+
+    return mat
+
+
+def c3sx_matrix():
+    """Compute unitary matrix for c3sx gate.
+    Args:
+        None.
+    Returns:
+        torch.Tensor: The computed unitary matrix.
+    """
+    mat = torch.eye(16, dtype=C_DTYPE)
+    mat[14][14] = (1 + 1j) / 2
+    mat[14][15] = (1 - 1j) / 2
+    mat[15][14] = (1 - 1j) / 2
+    mat[15][15] = (1 + 1j) / 2
+
+    return mat
+
+
 mat_dict = {
     "hadamard": torch.tensor(
         [[INV_SQRT2, INV_SQRT2], [INV_SQRT2, -INV_SQRT2]], dtype=C_DTYPE
@@ -1166,10 +1489,55 @@ def singleexcitation_matrix(params):
         ],
         dtype=C_DTYPE,
     ),
-    "ecr": torch.tensor(
+    "ecr": INV_SQRT2
+    * torch.tensor(
         [[0, 0, 1, 1j], [0, 0, 1j, 1], [1, -1j, 0, 0], [-1j, 1, 0, 0]], dtype=C_DTYPE
-    )
-    / np.sqrt(2),
+    ),
+    "sdg": torch.tensor([[1, 0], [0, -1j]], dtype=C_DTYPE),
+    "tdg": torch.tensor([[1, 0], [0, np.exp(-1j * np.pi / 4)]], dtype=C_DTYPE),
+    "sxdg": torch.tensor(
+        [[0.5 - 0.5j, 0.5 + 0.5j], [0.5 + 0.5j, 0.5 - 0.5j]], dtype=C_DTYPE
+    ),
+    "chadamard": torch.tensor(
+        [
+            [1, 0, 0, 0],
+            [0, 1, 0, 0],
+            [0, 0, INV_SQRT2, INV_SQRT2],
+            [0, 0, INV_SQRT2, -INV_SQRT2],
+        ],
+        dtype=C_DTYPE,
+    ),
+    "iswap": torch.tensor(
+        [[1, 0, 0, 0], [0, 0, 1j, 0], [0, 1j, 0, 0], [0, 0, 0, 1]], dtype=C_DTYPE
+    ),
+    "ccz": torch.tensor(
+        [
+            [1, 0, 0, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0, 0],
+            [0, 0, 1, 0, 0, 0, 0, 0],
+            [0, 0, 0, 1, 0, 0, 0, 0],
+            [0, 0, 0, 0, 1, 0, 0, 0],
+            [0, 0, 0, 0, 0, 1, 0, 0],
+            [0, 0, 0, 0, 0, 0, 1, 0],
+            [0, 0, 0, 0, 0, 0, 0, -1],
+        ],
+        dtype=C_DTYPE,
+    ),
+    "cs": torch.tensor(
+        [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1j]], dtype=C_DTYPE
+    ),
+    "csdg": torch.tensor(
+        [[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, -1j]], dtype=C_DTYPE
+    ),
+    "csx": torch.tensor(
+        [
+            [1, 0, 0, 0],
+            [0, 1, 0, 0],
+            [0, 0, 0.5 + 0.5j, 0.5 - 0.5j],
+            [0, 0, 0.5 - 0.5j, 0.5 + 0.5j],
+        ],
+        dtype=C_DTYPE,
+    ),
     "rx": rx_matrix,
     "ry": ry_matrix,
     "rz": rz_matrix,
@@ -1187,6 +1555,7 @@ def singleexcitation_matrix(params):
     "u1": u1_matrix,
     "u2": u2_matrix,
     "u3": u3_matrix,
+    "cu": cu_matrix,
     "cu1": cu1_matrix,
     "cu2": cu2_matrix,
     "cu3": cu3_matrix,
@@ -1196,6 +1565,51 @@ def singleexcitation_matrix(params):
     "multicnot": multicnot_matrix,
     "multixcnot": multixcnot_matrix,
     "singleexcitation": singleexcitation_matrix,
+    "qft": qft_matrix,
+    "dcx": torch.tensor(
+        [[1, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1], [0, 1, 0, 0]], dtype=C_DTYPE
+    ),
+    "xxminyy": xxminyy_matrix,
+    "xxplusyy": xxplusyy_matrix,
+    "r": r_matrix,
+    "globalphase": globalphase_matrix,
+    "c3x": c3x_matrix(),
+    "c4x": c4x_matrix(),
+    "c3sx": c3sx_matrix(),
+    "rccx": torch.tensor(
+        [
+            [1, 0, 0, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0, 0],
+            [0, 0, 1, 0, 0, 0, 0, 0],
+            [0, 0, 0, 1, 0, 0, 0, 0],
+            [0, 0, 0, 0, 1, 0, 0, 0],
+            [0, 0, 0, 0, 0, -1, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, -1j],
+            [0, 0, 0, 0, 0, 0, 1j, 0],
+        ],
+        dtype=C_DTYPE,
+    ),
+    "rc3x": torch.tensor(
+        [
+            [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1j, 0, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1j, 0, 0],
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+            [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 0],
+        ],
+        dtype=C_DTYPE,
+    ),
 }
 
 
@@ -2374,7 +2788,7 @@ def rot(
     )
 
 
-def multirz(
+def xxminyy(
     q_device,
     wires,
     params=None,
@@ -2384,7 +2798,7 @@ def multirz(
     inverse=False,
     comp_method="bmm",
 ):
-    """Perform the multi qubit RZ gate.
+    """Perform the XXminusYY gate.
 
     Args:
         q_device (tq.QuantumDevice): The QuantumDevice.
@@ -2405,7 +2819,7 @@ def multirz(
         None.
 
     """
-    name = "multirz"
+    name = "xxminyy"
     mat = mat_dict[name]
     gate_wrapper(
         name=name,
@@ -2421,7 +2835,7 @@ def multirz(
     )
 
 
-def crx(
+def xxplusyy(
     q_device,
     wires,
     params=None,
@@ -2431,7 +2845,7 @@ def crx(
     inverse=False,
     comp_method="bmm",
 ):
-    """Perform the crx gate.
+    """Perform the XXPlusYY gate.
 
     Args:
         q_device (tq.QuantumDevice): The QuantumDevice.
@@ -2452,7 +2866,7 @@ def crx(
         None.
 
     """
-    name = "crx"
+    name = "xxplusyy"
     mat = mat_dict[name]
     gate_wrapper(
         name=name,
@@ -2468,7 +2882,7 @@ def crx(
     )
 
 
-def cry(
+def multirz(
     q_device,
     wires,
     params=None,
@@ -2478,7 +2892,7 @@ def cry(
     inverse=False,
     comp_method="bmm",
 ):
-    """Perform the cry gate.
+    """Perform the multi qubit RZ gate.
 
     Args:
         q_device (tq.QuantumDevice): The QuantumDevice.
@@ -2499,7 +2913,7 @@ def cry(
         None.
 
     """
-    name = "cry"
+    name = "multirz"
     mat = mat_dict[name]
     gate_wrapper(
         name=name,
@@ -2515,7 +2929,7 @@ def cry(
     )
 
 
-def crz(
+def crx(
     q_device,
     wires,
     params=None,
@@ -2525,7 +2939,7 @@ def crz(
     inverse=False,
     comp_method="bmm",
 ):
-    """Perform the crz gate.
+    """Perform the crx gate.
 
     Args:
         q_device (tq.QuantumDevice): The QuantumDevice.
@@ -2546,7 +2960,7 @@ def crz(
         None.
 
     """
-    name = "crz"
+    name = "crx"
     mat = mat_dict[name]
     gate_wrapper(
         name=name,
@@ -2562,7 +2976,7 @@ def crz(
     )
 
 
-def crot(
+def cry(
     q_device,
     wires,
     params=None,
@@ -2572,7 +2986,7 @@ def crot(
     inverse=False,
     comp_method="bmm",
 ):
-    """Perform the crot gate.
+    """Perform the cry gate.
 
     Args:
         q_device (tq.QuantumDevice): The QuantumDevice.
@@ -2593,7 +3007,7 @@ def crot(
         None.
 
     """
-    name = "crot"
+    name = "cry"
     mat = mat_dict[name]
     gate_wrapper(
         name=name,
@@ -2609,7 +3023,7 @@ def crot(
     )
 
 
-def u1(
+def crz(
     q_device,
     wires,
     params=None,
@@ -2619,7 +3033,101 @@ def u1(
     inverse=False,
     comp_method="bmm",
 ):
-    """Perform the u1 gate.
+    """Perform the crz gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "crz"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def crot(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the crot gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "crot"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def u1(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the u1 gate.
 
     Args:
         q_device (tq.QuantumDevice): The QuantumDevice.
@@ -2750,6 +3258,50 @@ def u3(
     )
 
 
+def cu(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the cu gate.
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+    Returns:
+        None.
+    """
+    name = "cu"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
 def cu1(
     q_device,
     wires,
@@ -3032,6 +3584,53 @@ def qubitunitarystrict(
     )
 
 
+def c3x(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the c3x gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "c3x"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
 def multicnot(
     q_device,
     wires,
@@ -3221,25 +3820,799 @@ def ecr(
     )
 
 
-h = hadamard
-sh = shadamard
-x = paulix
-y = pauliy
-z = pauliz
-xx = rxx
-yy = ryy
-zz = rzz
-zx = rzx
-cx = cnot
-ccnot = toffoli
-ccx = toffoli
-u = u3
-cu = cu3
-p = phaseshift
-cp = cu1
-cr = cu1
-cphase = cu1
-echoedcrossresonance = ecr
+def qft(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    name = "qft"
+    if n_wires == None:
+        wires = [wires] if isinstance(wires, int) else wires
+        n_wires = len(wires)
+
+    mat = mat_dict[name]
+    # mat = qft_matrix(n_wires)
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def sdg(
+    q_device: QuantumDevice,
+    wires: Union[List[int], int],
+    params: torch.Tensor = None,
+    n_wires: int = None,
+    static: bool = False,
+    parent_graph=None,
+    inverse: bool = False,
+    comp_method: str = "bmm",
+):
+    """Perform the sdg gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "sdg"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def tdg(
+    q_device: QuantumDevice,
+    wires: Union[List[int], int],
+    params: torch.Tensor = None,
+    n_wires: int = None,
+    static: bool = False,
+    parent_graph=None,
+    inverse: bool = False,
+    comp_method: str = "bmm",
+):
+    """Perform the tdg gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "tdg"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def sxdg(
+    q_device: QuantumDevice,
+    wires: Union[List[int], int],
+    params: torch.Tensor = None,
+    n_wires: int = None,
+    static: bool = False,
+    parent_graph=None,
+    inverse: bool = False,
+    comp_method: str = "bmm",
+):
+    """Perform the sxdg gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "sxdg"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def chadamard(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the chadamard gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+
+    name = "chadamard"
+
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def ccz(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the ccz gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "ccz"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def iswap(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the iswap gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "iswap"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def cs(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the cs gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+
+    name = "cs"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def csdg(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the csdg gate.
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+
+    Returns:
+        None.
+
+    """
+    name = "csdg"
+
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def csx(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the csx gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "csx"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def dcx(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the dcx gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "dcx"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def r(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the R gate.
+
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+
+    Returns:
+        None.
+
+    """
+    name = "r"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def c4x(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the c4x gate.
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+    Returns:
+        None.
+    """
+    name = "c4x"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def rc3x(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the rc3x (simplified 3-controlled Toffoli) gate.
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+    Returns:
+        None.
+    """
+    name = "rc3x"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def rccx(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the rccx (simplified Toffoli) gate.
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+    Returns:
+        None.
+    """
+    name = "rccx"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def globalphase(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the echoed cross-resonance gate.
+    https://qiskit.org/documentation/stubs/qiskit.circuit.library.ECRGate.html
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+    Returns:
+        None.
+    """
+    name = "globalphase"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+def c3sx(
+    q_device,
+    wires,
+    params=None,
+    n_wires=None,
+    static=False,
+    parent_graph=None,
+    inverse=False,
+    comp_method="bmm",
+):
+    """Perform the c3sx gate.
+    Args:
+        q_device (tq.QuantumDevice): The QuantumDevice.
+        wires (Union[List[int], int]): Which qubit(s) to apply the gate.
+        params (torch.Tensor, optional): Parameters (if any) of the gate.
+            Default to None.
+        n_wires (int, optional): Number of qubits the gate is applied to.
+            Default to None.
+        static (bool, optional): Whether use static mode computation.
+            Default to False.
+        parent_graph (tq.QuantumGraph, optional): Parent QuantumGraph of
+            current operation. Default to None.
+        inverse (bool, optional): Whether inverse the gate. Default to False.
+        comp_method (bool, optional): Use 'bmm' or 'einsum' method to perform
+        matrix vector multiplication. Default to 'bmm'.
+    Returns:
+        None.
+    """
+    name = "c3sx"
+    mat = mat_dict[name]
+    gate_wrapper(
+        name=name,
+        mat=mat,
+        method=comp_method,
+        q_device=q_device,
+        wires=wires,
+        params=params,
+        n_wires=n_wires,
+        static=static,
+        parent_graph=parent_graph,
+        inverse=inverse,
+    )
+
+
+h = hadamard
+sh = shadamard
+x = paulix
+y = pauliy
+z = pauliz
+xx = rxx
+yy = ryy
+zz = rzz
+zx = rzx
+cx = cnot
+ccnot = toffoli
+ccx = toffoli
+u = u3
+p = phaseshift
+cp = cu1
+cr = cu1
+cphase = cu1
+echoedcrossresonance = ecr
+ch = chadamard
+
 
 func_name_dict = {
     "hadamard": hadamard,
@@ -3304,4 +4677,26 @@ def ecr(
     "singleexcitation": singleexcitation,
     "ecr": ecr,
     "echoedcrossresonance": echoedcrossresonance,
+    "qft": qft,
+    "sdg": sdg,
+    "tdg": tdg,
+    "sxdg": sxdg,
+    "ch": ch,
+    "ccz": ccz,
+    "iswap": iswap,
+    "cs": cs,
+    "csdg": csdg,
+    "csx": csx,
+    "chadamard": chadamard,
+    "ccz": ccz,
+    "dcx": dcx,
+    "xxminyy": xxminyy,
+    "xxplusyy": xxplusyy,
+    "c3x": c3x,
+    "r": r,
+    "globalphase": globalphase,
+    "c3sx": c3sx,
+    "rccx": rccx,
+    "rc3x": rc3x,
+    "c4x": c4x,
 }
diff --git a/torchquantum/graph/__init__.py b/torchquantum/graph/__init__.py
new file mode 100644
index 00000000..c2488bbd
--- /dev/null
+++ b/torchquantum/graph/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .graphs import *
diff --git a/torchquantum/graph.py b/torchquantum/graph/graphs.py
similarity index 63%
rename from torchquantum/graph.py
rename to torchquantum/graph/graphs.py
index b0916678..0dd7baa1 100644
--- a/torchquantum/graph.py
+++ b/torchquantum/graph/graphs.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torchquantum as tq
 import torchquantum.functional as tqf
@@ -10,14 +34,38 @@
 
 
 def encode_w(wires):
+    """Encode a list of wires into a string representation.
+
+        Args:
+            wires (list[int]): List of wire indices.
+
+        Returns:
+            str: String representation of the wires.
+        """
     return ".".join(list(map(str, wires)))
 
 
 def decode_w(w):
+    """Decode a string representation of wires into a list.
+
+        Args:
+            w (str): String representation of wires.
+
+        Returns:
+            list[int]: List of wire indices.
+        """
     return list(map(eval, w.split(".")))
 
 
 def static_support(f):
+    """Decorator for static support in QuantumGraph class.
+
+        Args:
+            f (function): Function to be decorated.
+
+        Returns:
+            function: Decorated function.
+        """
     @functools.wraps(f)
     def forward_register_graph(*args, **kwargs):
         if args[0].static_mode and args[0].parent_graph is not None:
@@ -34,6 +82,28 @@ def forward_register_graph(*args, **kwargs):
 
 
 class QuantumGraph(object):
+    """
+       The QuantumGraph class is used to construct and execute a quantum graph
+       consisting of quantum operations.
+
+       Attributes:
+           is_list_finish (bool): Flag indicating if the module list construction is finished.
+           module_list (list): List of quantum operations in the graph.
+           flat_module_list (list): Flattened list of quantum operations in the graph.
+           wire_module_dict (dict): Dictionary mapping wires to the corresponding quantum operations.
+           wire_module_list (list): List of quantum operations for each wire.
+           local2global_wire_mapping (dict): Dictionary mapping local wire indices to global wire indices.
+           global2local_wire_mapping (dict): Dictionary mapping global wire indices to local wire indices.
+           schedules (list): List of schedules for executing the quantum operations.
+           q_device: Quantum device.
+           device: Device (CPU/GPU) for execution.
+           func_list (list): List of functional operations in the graph.
+           func_ptr (int): Pointer to the current functional operation.
+           num_func (int): Total number of functional operations.
+           build_finish (bool): Flag indicating if the graph construction is finished.
+           static_matrix_dict (dict): Dictionary mapping operation names to their static matrices.
+       """
+
     def __init__(self):
         self.is_list_finish = False
         self.module_list = []
@@ -53,6 +123,11 @@ def __init__(self):
         self.static_matrix_dict = {}
 
     def add_op(self, op: tq.Operator):
+        """Add a quantum operation to the graph.
+
+                Args:
+                    op (QuantumModule): Quantum operation to be added to the graph.
+                """
         if not self.is_list_finish:
             # graph construction is not finished, add the operation
             self.module_list.append(op)
@@ -63,6 +138,21 @@ def add_op(self, op: tq.Operator):
     def add_func(
         self, name, wires, parent_graph, params=None, n_wires=None, inverse=False
     ):
+        """Add a quantum function to the module.
+
+            If the graph construction is not finished, a new operation is built and added
+            to the graph. If the graph construction is finished, the parameters of the new
+            operation are updated.
+
+            Args:
+                name (str): Name of the quantum function.
+                wires (list[int]): List of wire indices used by the function.
+                parent_graph (QuantumGraph): Parent quantum graph of the function.
+                params (Any): Parameters of the function (optional).
+                n_wires (int): Number of wires used by the function (optional).
+                inverse (bool): Flag indicating if the function should be inverted (optional).
+            """
+
         if not self.is_list_finish:
             # graph construction is not finished, build a new operation and
             # add the operation to the graph
@@ -87,6 +177,21 @@ def add_func(
             self.func_ptr = (self.func_ptr + 1) % self.num_func
 
     def build(self, wires_per_block):
+        """Build the quantum module.
+
+           This method performs various steps to construct the quantum module, including:
+           - Building wire-module dictionary
+           - Building local wire-module list
+           - Building flat module list
+           - Building schedule blockwise
+           - Setting the build_finish flag
+
+           Args:
+               wires_per_block (int): Number of wires per block.
+
+           Returns:
+               None
+           """
         self.build_wire_module_dict(self.module_list)
         self.build_local_wire_module_list()
         self.build_flat_module_list(self.module_list)
@@ -95,6 +200,19 @@ def build(self, wires_per_block):
         self.build_finish = True
 
     def forward(self, wires_per_block):
+        """Forward pass of the quantum module.
+
+            If the module is not built yet, it calls the `build` method to construct
+            the quantum module. Then, it performs the following steps:
+            - Builds the static matrix
+            - Applies the unitary transformation
+
+            Args:
+                wires_per_block (int): Number of wires per block.
+
+            Returns:
+                None
+            """
         if not self.build_finish:
             self.build(wires_per_block)
 
@@ -102,6 +220,15 @@ def forward(self, wires_per_block):
         self.apply_unitary()
 
     def build_static_matrix(self):
+        """Builds the static matrix for the quantum module.
+
+            The method performs the following steps:
+            - Optimizes the static mode by sharing static matrices for fixed unitary operators and computing matrices for parameterized operators together
+            - Constructs the static matrices for each module based on their type and parameters
+
+            Returns:
+                None
+            """
         # the optimization to speedup the static mode
         # 1. fixed unitary operators will share one matrix
         # 2. parameterized operators, the matrices for the same type are
@@ -185,6 +312,19 @@ def build_static_matrix(self):
                 raise NotImplementedError(f"Module {name} not in list")
 
     def build_wire_module_dict(self, module_list):
+        """Builds a dictionary mapping wires to their associated modules.
+
+            The method recursively traverses the module list and constructs a dictionary
+            that maps each wire to the modules it belongs to. For leaf nodes, i.e., modules
+            with an empty module list, the wire is added to the dictionary. For non-leaf nodes,
+            the method recursively calls itself on the module list of the current module.
+
+            Args:
+                module_list (list[QuantumModule]): The list of modules to build the wire-module dictionary for.
+
+            Returns:
+                None
+            """
         for module in module_list:
             if len(module.graph.module_list) == 0:
                 # leaf node
@@ -197,6 +337,20 @@ def build_wire_module_dict(self, module_list):
                 self.build_wire_module_dict(module.graph.module_list)
 
     def build_flat_module_list(self, module_list=None):
+        """Builds a flat list of modules from a nested module list.
+
+           The method recursively traverses the module list and constructs a flat list
+           of modules by appending leaf nodes (modules without a nested module list)
+           to the flat module list. It also checks for modules with no operations and
+           logs a warning if found.
+
+           Args:
+               module_list (list[QuantumModule], optional): The module list to build the flat module list from.
+                   If not provided, the instance's `module_list` attribute is used as the default.
+
+           Returns:
+               None
+           """
         if module_list is None:
             module_list = self.module_list
         for module in module_list:
@@ -211,6 +365,14 @@ def build_flat_module_list(self, module_list=None):
                 self.build_flat_module_list(module.graph.module_list)
 
     def build_local_wire_module_list(self):
+        """Builds local wire module lists and wire mappings.
+
+            The method constructs local wire module lists by assigning local wire indices
+            to the global wires. It also builds mappings between local and global wire indices.
+
+            Returns:
+                None
+            """
         global_wires = sorted(list(self.wire_module_dict.keys()))
         local_wires = list(range(len(global_wires)))
 
@@ -220,6 +382,21 @@ def build_local_wire_module_list(self):
             self.wire_module_list.append(self.wire_module_dict[global_wire])
 
     def build_schedule_blockwise(self, wires_per_block):
+        """Builds the schedule for block-wise execution.
+
+          The method greedily searches for the block containing the highest number of gates per block.
+          The number of wires per block is specified as a hyperparameter. It iteratively adds gates to
+          the schedule until all gates have been scheduled.
+
+          Args:
+              wires_per_block (int): The number of wires in each block.
+
+          Returns:
+              list[dict]: A list of dictionaries representing the schedule. Each dictionary contains
+                          the wires involved in the block and the modules (gates) to be executed on
+                          those wires.
+
+          """
         # greedily search for the block containing most number of gates per
         # block. The block contains wires_per_block wires as a hyper-parameter
         n_wires = len(self.wire_module_list)
@@ -227,14 +404,37 @@ def build_schedule_blockwise(self, wires_per_block):
         wire_module_len = [len(wire_module) for wire_module in self.wire_module_list]
 
         def schedule_finish():
+            """Checks if the scheduling process is complete.
+
+                    Returns:
+                        bool: True if scheduling is complete, False otherwise.
+                    """
             return all(
                 [module_ptrs[k] == wire_module_len[k] for k in range(len(module_ptrs))]
             )
 
         def is_front(wires, ptrs):
+            """Checks if the gates specified by `wires` are at the front of their respective modules.
+
+                    Args:
+                        wires (list[int]): List of wire indices.
+                        ptrs (list[int]): List of pointers indicating the current position in the modules.
+
+                    Returns:
+                        bool: True if gates are at the front, False otherwise.
+                    """
             return len(set([id(self.wire_module_list[w][ptrs[w]]) for w in wires])) == 1
 
         def add_front_large_qubit_gate(ptrs, sches):
+            """Adds large qubit gates at the front of the schedule if the number of wires in a block is smaller.
+
+                    Args:
+                        ptrs (list[int]): List of pointers indicating the current position in the modules.
+                        sches (list[dict]): List of dictionaries representing the schedule.
+
+                    Returns:
+                        None
+                    """
             # deal with the case when the number of wires in a block is
             # smaller than the number of wires in a gate
             for w in range(n_wires):
@@ -257,9 +457,27 @@ def add_front_large_qubit_gate(ptrs, sches):
                             ptrs[local_w] += 1
 
         def comb_finish(combination, ptrs):
+            """Checks if all gates in the combination have been scheduled.
+
+                    Args:
+                        combination (list[int]): List of wire indices representing a combination of wires.
+                        ptrs (list[int]): List of pointers indicating the current position in the modules.
+
+                    Returns:
+                        bool: True if all gates in the combination have been scheduled, False otherwise.
+                    """
             return all(ptrs[w] == wire_module_len[w] for w in combination)
 
         def wires_in_comb(wires, combination):
+            """Checks if all wires are present in the combination.
+
+                   Args:
+                       wires (list[int]): List of wire indices.
+                       combination (list[int]): List of wire indices representing a combination of wires.
+
+                   Returns:
+                       bool: True if all wires are present in the combination, False otherwise.
+                   """
             return all([w in combination for w in wires])
 
         schedules = []
@@ -314,6 +532,17 @@ def wires_in_comb(wires, combination):
         return schedules
 
     def build_schedule_layerwise(self):
+        """Builds the schedule for layer-wise execution.
+
+            The method merges multiple consecutive operations applied to the same wires into one scheduled layer.
+            It iteratively adds operations to the schedule until all operations have been scheduled.
+
+            Returns:
+                list[dict]: A list of dictionaries representing the schedule. Each dictionary contains
+                            the wire combination involved in the layer and the operations to be executed
+                            on those wires.
+
+            """
         # if multiple consecutive gate are applied to the same wires,
         # then merge them together in one scheduled layer
         n_wires = len(self.wire_module_list)
@@ -322,11 +551,25 @@ def build_schedule_layerwise(self):
         wire_module_len = [len(wire_module) for wire_module in self.wire_module_list]
 
         def schedule_finish():
+            """Checks if the scheduling process is complete.
+
+                   Returns:
+                       bool: True if scheduling is complete, False otherwise.
+                   """
             return all(
                 [module_ptrs[k] == wire_module_len[k] for k in range(len(module_ptrs))]
             )
 
         def is_front(op, ptrs):
+            """Checks if the given operation is at the front of its respective module.
+
+                    Args:
+                        op (tq.Operator): The operation.
+                        ptrs (list[int]): List of pointers indicating the current position in the modules.
+
+                    Returns:
+                        bool: True if the operation is at the front, False otherwise.
+                    """
             ws = [self.global2local_wire_mapping[w] for w in op.wires]
             is_all_front = True
             for w in ws:
@@ -336,10 +579,28 @@ def is_front(op, ptrs):
             return is_all_front
 
         def update_ptrs(ws, ptrs):
+            """Updates the pointers for the given wires.
+
+                    Args:
+                        ws (list[int]): List of wire indices.
+                        ptrs (list[int]): List of pointers indicating the current position in the modules.
+
+                    Returns:
+                        None
+                    """
             for w in ws:
                 ptrs[w] += 1
 
         def has_conflict(wire_pairs, wires):
+            """Checks if there is a conflict between the given wire pairs and wires.
+
+                    Args:
+                        wire_pairs (list[tuple[int]]): List of wire pairs.
+                        wires (list[int]): List of wire indices.
+
+                    Returns:
+                        bool: True if there is a conflict, False otherwise.
+                    """
             if encode_w(wires) in wire_pairs:
                 conflict = False
             else:
@@ -450,6 +711,17 @@ def acc_m_unitary_einsum(u, wires, module):
 
     @staticmethod
     def acc_m_unitary_bmm(u, global_wires, module):
+        """Updates the unitary tensor using Einsum.
+
+           Args:
+               u (torch.Tensor): The input unitary tensor.
+               wires (list[int]): List of wire indices.
+               module (tq.Operator): The module (gate) applied to the wires.
+
+           Returns:
+               torch.Tensor: The updated unitary tensor.
+
+           """
         # compute the unitary of each block and apply to the device
         if u.dim() % 2 == 1:
             is_u_batch = True
@@ -532,6 +804,15 @@ def get_unitary(self):
         return self.get_schedule_unitary(self.schedules[0])
 
     def get_schedule_unitary(self, schedule):
+        """Computes the unitary for a given schedule.
+
+            Args:
+                schedule (dict): The schedule containing the wires and modules.
+
+            Returns:
+                torch.Tensor: The unitary tensor corresponding to the given schedule.
+
+            """
         # here some front large gates will need a larger unitary
         unitary = torch.eye(
             2**self.q_device.n_wires, dtype=C_DTYPE, device=self.device
@@ -553,6 +834,12 @@ def get_schedule_unitary(self, schedule):
         return unitary
 
     def apply_unitary(self):
+        """Applies the unitary transformations to the quantum device based on the schedules.
+
+            Returns:
+                None
+
+            """
         for schedule in self.schedules:
             comb = schedule["wires"]
             # here some front large gates will need a larger unitary
diff --git a/torchquantum/layer/__init__.py b/torchquantum/layer/__init__.py
new file mode 100644
index 00000000..a6c99385
--- /dev/null
+++ b/torchquantum/layer/__init__.py
@@ -0,0 +1,26 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .layers import *
+from .nlocal import *
diff --git a/torchquantum/layer/layers.py b/torchquantum/layer/layers.py
new file mode 100644
index 00000000..bd88fb13
--- /dev/null
+++ b/torchquantum/layer/layers.py
@@ -0,0 +1,1637 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torch.nn as nn
+import torchquantum as tq
+import torchquantum.functional as tqf
+import numpy as np
+
+
+from typing import Iterable
+from torchquantum.plugin.qiskit import QISKIT_INCOMPATIBLE_FUNC_NAMES
+from torchpack.utils.logging import logger
+
+__all__ = [
+    "QuantumModuleFromOps",
+    "TrainableOpAll",
+    "ClassicalInOpAll",
+    "FixedOpAll",
+    "TwoQAll",
+    "RandomLayer",
+    "RandomLayerAllTypes",
+    "Op1QAllLayer",
+    "RandomOp1All",
+    "Op2QAllLayer",
+    "Op2QButterflyLayer",
+    "Op2QDenseLayer",
+    "layer_name_dict",
+    "CXLayer",
+    "CXCXCXLayer",
+    "SWAPSWAPLayer",
+    "RXYZCXLayer0",
+    "QFTLayer",
+]
+
+
+class QuantumModuleFromOps(tq.QuantumModule):
+    """Initializes a QuantumModuleFromOps instance.
+
+            Args:
+                ops (List[tq.Operation]): List of quantum operations.
+
+            """
+    def __init__(self, ops):
+        super().__init__()
+        self.ops = tq.QuantumModuleList(ops)
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice):
+        """Performs the forward pass of the quantum module.
+
+               Args:
+                   q_device (tq.QuantumDevice): Quantum device to apply the operations on.
+
+               Returns:
+                   None
+
+               """
+        self.q_device = q_device
+        for op in self.ops:
+            op(q_device)
+
+
+class TrainableOpAll(tq.QuantumModule):
+    """Rotation rx on all qubits
+    The rotation angle is a parameter of each rotation gate
+    One potential optimization is to compute the unitary of all gates
+    together.
+    """
+
+    def __init__(self, n_gate: int, op: tq.Operation):
+        super().__init__()
+        self.n_gate = n_gate
+        self.gate_all = nn.ModuleList()
+        for k in range(self.n_gate):
+            self.gate_all.append(op(has_params=True, trainable=True))
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice):
+        # rx on all wires, assert the number of gate is the same as the number
+        # of wires in the device.
+        assert self.n_gate == q_device.n_wires, (
+            f"Number of rx gates ({self.n_gate}) is different from number "
+            f"of wires ({q_device.n_wires})!"
+        )
+
+        for k in range(self.n_gate):
+            self.gate_all[k](q_device, wires=k)
+
+
+class ClassicalInOpAll(tq.QuantumModule):
+    """
+      Quantum module that applies the same quantum operation to all wires of a quantum device,
+      where the parameters of the operation are obtained from a classical input.
+
+      Args:
+          n_gate (int): Number of gates.
+          op (tq.Operator): Quantum operation to be applied.
+
+      Attributes:
+          n_gate (int): Number of gates.
+          gate_all (nn.ModuleList): List of quantum operations.
+
+      """
+    def __init__(self, n_gate: int, op: tq.Operator):
+        super().__init__()
+        self.n_gate = n_gate
+        self.gate_all = nn.ModuleList()
+        for k in range(self.n_gate):
+            self.gate_all.append(op())
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice, x):
+        """
+               Performs the forward pass of the classical input quantum operation module.
+
+               Args:
+                   q_device (tq.QuantumDevice): Quantum device to apply the operations on.
+                   x (torch.Tensor): Classical input of shape (batch_size, n_gate).
+
+               Returns:
+                   None
+
+               Raises:
+                   AssertionError: If the number of gates is different from the number of wires in the device.
+
+               """
+        # rx on all wires, assert the number of gate is the same as the number
+        # of wires in the device.
+        assert self.n_gate == q_device.n_wires, (
+            f"Number of rx gates ({self.n_gate}) is different from number "
+            f"of wires ({q_device.n_wires})!"
+        )
+
+        for k in range(self.n_gate):
+            self.gate_all[k](q_device, wires=k, params=x[:, k])
+
+
+class FixedOpAll(tq.QuantumModule):
+    """
+       Quantum module that applies the same fixed quantum operation to all wires of a quantum device.
+
+       Args:
+           n_gate (int): Number of gates.
+           op (tq.Operator): Quantum operation to be applied.
+
+       Attributes:
+           n_gate (int): Number of gates.
+           gate_all (nn.ModuleList): List of quantum operations.
+
+       """
+    def __init__(self, n_gate: int, op: tq.Operator):
+        super().__init__()
+        self.n_gate = n_gate
+        self.gate_all = nn.ModuleList()
+        for k in range(self.n_gate):
+            self.gate_all.append(op())
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice):
+        """
+                Performs the forward pass of the fixed quantum operation module.
+
+                Args:
+                    q_device (tq.QuantumDevice): Quantum device to apply the operations on.
+
+                Returns:
+                    None
+
+                Raises:
+                    AssertionError: If the number of gates is different from the number of wires in the device.
+
+                """
+        # rx on all wires, assert the number of gate is the same as the number
+        # of wires in the device.
+        assert self.n_gate == q_device.n_wires, (
+            f"Number of rx gates ({self.n_gate}) is different from number "
+            f"of wires ({q_device.n_wires})!"
+        )
+
+        for k in range(self.n_gate):
+            self.gate_all[k](q_device, wires=k)
+
+
+class TwoQAll(tq.QuantumModule):
+    """
+        Quantum module that applies a two-qubit quantum operation to adjacent pairs of wires in a quantum device.
+
+        Args:
+            n_gate (int): Number of adjacent pairs of wires.
+            op (tq.Operator): Two-qubit quantum operation to be applied.
+
+        Attributes:
+            n_gate (int): Number of adjacent pairs of wires.
+            op (tq.Operator): Two-qubit quantum operation.
+
+        """
+    def __init__(self, n_gate: int, op: tq.Operator):
+        super().__init__()
+        self.n_gate = n_gate
+        self.op = op()
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice):
+        for k in range(self.n_gate - 1):
+            self.op(q_device, wires=[k, k + 1])
+        self.op(q_device, wires=[self.n_gate - 1, 0])
+
+
+class RandomOp1All(tq.QuantumModule):
+    def __init__(
+        self, n_wires: int, op_types=(tq.RX, tq.RY, tq.RZ), op_ratios=None, seed=None
+    ):
+        """Layer adding a random gate to all wires
+
+        Params:
+            n_wires (int): number of wires/gates in integer format
+            op_types (Iterable): single-wire gates to select from in iterable format
+            op_ratios (Iterable): probabilities to select each gate option in iterable format
+            seed (int): random seed in integer format
+        """
+        super().__init__()
+        self.n_wires = n_wires
+        self.op_types = op_types
+        self.op_ratios = op_ratios
+        self.seed = seed
+        self.gate_all = nn.ModuleList()
+        if seed is not None:
+            np.random.seed(seed)
+        self.build_random_layer()
+
+    def build_random_layer(self):
+        for k in range(self.n_wires):
+            op = np.random.choice(self.op_types, p=self.op_ratios)
+            self.gate_all.append(op())
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice, x):
+        # op on all wires, assert the number of gate is the same as the number
+        # of wires in the device.
+        assert self.n_gate == q_device.n_wires, (
+            f"Number of gates ({self.n_wires}) is different from number "
+            f"of wires ({q_device.n_wires})!"
+        )
+
+        for k in range(self.n_wires):
+            self.gate_all[k](q_device, wires=k, params=x[:, k])
+
+
+class RandomLayer(tq.QuantumModule):
+    """
+        Quantum module that represents a random layer of quantum operations applied to specified wires.
+
+        Args:
+            wires (int or Iterable[int]): Indices of the wires the operations are applied to.
+            n_ops (int): Number of random operations in the layer.
+            n_params (int): Number of parameters for each random operation.
+            op_ratios (list or float): Ratios determining the relative frequencies of different operation types.
+            op_types (tuple or tq.Operator): Types of random operations to be included in the layer.
+            seed (int): Seed for random number generation.
+            qiskit_compatible (bool): Flag indicating whether the layer should be compatible with Qiskit.
+
+        Attributes:
+            n_ops (int): Number of random operations in the layer.
+            n_params (int): Number of parameters for each random operation.
+            wires (list): Indices of the wires the operations are applied to.
+            n_wires (int): Number of wires.
+            op_types (list): Types of random operations included in the layer.
+            op_ratios (numpy.array): Ratios determining the relative frequencies of different operation types.
+            seed (int): Seed for random number generation.
+            op_list (tq.QuantumModuleList): List of random operations in the layer.
+
+        """
+    def __init__(
+        self,
+        wires,
+        n_ops=None,
+        n_params=None,
+        op_ratios=None,
+        op_types=(tq.RX, tq.RY, tq.RZ, tq.CNOT),
+        seed=None,
+        qiskit_compatible=False,
+    ):
+        super().__init__()
+        self.n_ops = n_ops
+        self.n_params = n_params
+        assert n_params is not None or n_ops is not None
+        self.wires = wires if isinstance(wires, Iterable) else [wires]
+        self.n_wires = len(wires)
+
+        op_types = op_types if isinstance(op_types, Iterable) else [op_types]
+        if op_ratios is None:
+            op_ratios = [1] * len(op_types)
+        else:
+            op_ratios = op_ratios if isinstance(op_ratios, Iterable) else [op_ratios]
+        op_types_valid = []
+        op_ratios_valid = []
+
+        if qiskit_compatible:
+            for op_type, op_ratio in zip(op_types, op_ratios):
+                if op_type().name.lower() in QISKIT_INCOMPATIBLE_FUNC_NAMES:
+                    logger.warning(
+                        f"Remove {op_type} from op_types to make "
+                        f"the layer qiskit-compatible."
+                    )
+                else:
+                    op_types_valid.append(op_type)
+                    op_ratios_valid.append(op_ratio)
+        else:
+            op_types_valid = op_types
+            op_ratios_valid = op_ratios
+
+        self.op_types = op_types_valid
+        self.op_ratios = np.array(op_ratios_valid) / sum(op_ratios_valid)
+
+        self.seed = seed
+        self.op_list = tq.QuantumModuleList()
+        if seed is not None:
+            np.random.seed(seed)
+        self.build_random_layer()
+
+    def rebuild_random_layer_from_op_list(self, n_ops_in, wires_in, op_list_in):
+        """
+           Rebuilds a random layer from the given operation list.
+           This method is used for loading a random layer from a checkpoint.
+
+           Args:
+               n_ops_in (int): Number of operations in the layer.
+               wires_in (list): Indices of the wires the operations are applied to.
+               op_list_in (list): List of operations in the layer.
+
+           """
+
+        self.n_ops = n_ops_in
+        self.wires = wires_in
+        self.op_list = tq.QuantumModuleList()
+        for op_in in op_list_in:
+            op = tq.op_name_dict[op_in.name.lower()](
+                has_params=op_in.has_params,
+                trainable=op_in.trainable,
+                wires=op_in.wires,
+                n_wires=op_in.n_wires,
+            )
+            self.op_list.append(op)
+
+    def build_random_layer(self):
+        op_cnt = 0
+        param_cnt = 0
+        while True:
+            op = np.random.choice(self.op_types, p=self.op_ratios)
+            n_op_wires = op.num_wires
+            if n_op_wires > self.n_wires:
+                continue
+            if n_op_wires == -1:
+                is_AnyWire = True
+                n_op_wires = self.n_wires
+            else:
+                is_AnyWire = False
+
+            op_wires = list(
+                np.random.choice(self.wires, size=n_op_wires, replace=False)
+            )
+            if is_AnyWire:
+                if op().name in ["MultiRZ"]:
+                    operation = op(
+                        has_params=True,
+                        trainable=True,
+                        n_wires=n_op_wires,
+                        wires=op_wires,
+                    )
+                else:
+                    operation = op(n_wires=n_op_wires, wires=op_wires)
+            elif op().name in tq.Operator.parameterized_ops:
+                operation = op(has_params=True, trainable=True, wires=op_wires)
+            else:
+                operation = op(wires=op_wires)
+            self.op_list.append(operation)
+            op_cnt += 1
+            param_cnt += op.num_params
+
+            if self.n_ops is not None and op_cnt == self.n_ops:
+                break
+            elif self.n_ops is None and self.n_params is not None:
+                if param_cnt == self.n_params:
+                    break
+                elif param_cnt > self.n_params:
+                    """
+                    the last operation has too many params and exceed the
+                    constraint, so need to remove it and sample another
+                    """
+                    op_cnt -= 1
+                    param_cnt -= op.num_params
+                    del self.op_list[-1]
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice):
+        for op in self.op_list:
+            op(q_device)
+
+
+class RandomLayerAllTypes(RandomLayer):
+    """
+       Random layer with a wide range of quantum gate types.
+
+       This class extends the `RandomLayer` class to include a variety of quantum gate types as options for the random layer.
+
+       Args:
+           wires (int or list): Indices of the wires the operations are applied to.
+           n_ops (int): Number of operations in the layer.
+           n_params (int): Number of parameters for each operation.
+           op_ratios (list): Ratios for selecting different types of operations.
+           op_types (tuple): Types of operations to include in the layer.
+           seed (int): Seed for the random number generator.
+           qiskit_compatible (bool): Flag indicating whether the layer should be Qiskit-compatible.
+
+       """
+    def __init__(
+        self,
+        wires,
+        n_ops=None,
+        n_params=None,
+        op_ratios=None,
+        op_types=(
+            tq.Hadamard,
+            tq.SHadamard,
+            tq.PauliX,
+            tq.PauliY,
+            tq.PauliZ,
+            tq.S,
+            tq.T,
+            tq.SX,
+            tq.CNOT,
+            tq.CZ,
+            tq.CY,
+            tq.RX,
+            tq.RY,
+            tq.RZ,
+            tq.RZZ,
+            tq.SWAP,
+            tq.CSWAP,
+            tq.Toffoli,
+            tq.PhaseShift,
+            tq.Rot,
+            tq.MultiRZ,
+            tq.CRX,
+            tq.CRY,
+            tq.CRZ,
+            tq.CRot,
+            tq.U1,
+            tq.U2,
+            tq.U3,
+            tq.MultiCNOT,
+            tq.MultiXCNOT,
+        ),
+        seed=None,
+        qiskit_compatible=False,
+    ):
+        super().__init__(
+            wires=wires,
+            n_ops=n_ops,
+            n_params=n_params,
+            op_ratios=op_ratios,
+            op_types=op_types,
+            seed=seed,
+            qiskit_compatible=qiskit_compatible,
+        )
+
+
+class SimpleQLayer(tq.QuantumModule):
+    """
+       Simple quantum layer consisting of three parameterized gates applied to specific wires.
+
+       This class represents a simple quantum layer with three parameterized gates: RX, RY, and RZ. The gates are applied to specific wires in the quantum device.
+
+       Args:
+           n_wires (int): Number of wires in the quantum device.
+
+       """
+    def __init__(self, n_wires):
+        super().__init__()
+        self.n_wires = n_wires
+        self.gate1 = tq.RX(has_params=True, trainable=True)
+        self.gate2 = tq.RY(has_params=True, trainable=True)
+        self.gate3 = tq.RZ(has_params=True, trainable=True)
+
+    @tq.static_support
+    def forward(self, q_dev):
+        self.q_device = q_dev
+        tqf.x(q_dev, wires=0, static=self.static_mode, parent_graph=self.graph)
+        self.gate1(q_dev, wires=1)
+        self.gate2(q_dev, wires=1)
+        self.gate3(q_dev, wires=1)
+        tqf.x(q_dev, wires=2, static=self.static_mode, parent_graph=self.graph)
+
+
+class CXLayer(tq.QuantumModule):
+    """
+        Quantum layer with a controlled-X (CX) gate applied to two specified wires.
+
+        This class represents a quantum layer with a controlled-X (CX) gate applied to two specified wires in the quantum device.
+
+        Args:
+            n_wires (int): Number of wires in the quantum device.
+
+        """
+    def __init__(self, n_wires):
+        super().__init__()
+        self.n_wires = n_wires
+
+    @tq.static_support
+    def forward(self, q_dev):
+        self.q_device = q_dev
+        tqf.cnot(q_dev, wires=[0, 1], static=self.static_mode, parent_graph=self.graph)
+
+
+class CXCXCXLayer(tq.QuantumModule):
+    """
+       Quantum layer with a sequence of CX gates applied to three specified wires.
+
+       This class represents a quantum layer with a sequence of CX gates applied to three specified wires in the quantum device.
+
+       Args:
+           n_wires (int): Number of wires in the quantum device.
+
+       """
+    def __init__(self, n_wires):
+        super().__init__()
+        self.n_wires = n_wires
+
+    @tq.static_support
+    def forward(self, q_dev):
+        self.q_device = q_dev
+        tqf.cnot(q_dev, wires=[0, 1], static=self.static_mode, parent_graph=self.graph)
+        tqf.cnot(q_dev, wires=[1, 2], static=self.static_mode, parent_graph=self.graph)
+        tqf.cnot(q_dev, wires=[2, 0], static=self.static_mode, parent_graph=self.graph)
+
+
+class SWAPSWAPLayer(tq.QuantumModule):
+    """
+       Quantum layer with a sequence of SWAP gates applied to two specified pairs of wires.
+
+       This class represents a quantum layer with a sequence of SWAP gates applied to two specified pairs of wires in the quantum device.
+
+       Args:
+           n_wires (int): Number of wires in the quantum device.
+
+       """
+    def __init__(self, n_wires):
+        super().__init__()
+        self.n_wires = n_wires
+
+    @tq.static_support
+    def forward(self, q_dev):
+        self.q_device = q_dev
+        tqf.swap(q_dev, wires=[0, 1], static=self.static_mode, parent_graph=self.graph)
+        tqf.swap(q_dev, wires=[1, 2], static=self.static_mode, parent_graph=self.graph)
+
+
+class Op1QAllLayer(tq.QuantumModule):
+    """
+        Quantum layer applying the same single-qubit operation to all wires.
+
+        This class represents a quantum layer that applies the same single-qubit operation to all wires in the quantum device.
+
+        Args:
+            op (tq.Operator): Single-qubit operation to be applied.
+            n_wires (int): Number of wires in the quantum device.
+            has_params (bool, optional): Flag indicating if the operation has parameters. Defaults to False.
+            trainable (bool, optional): Flag indicating if the operation is trainable. Defaults to False.
+
+        """
+    def __init__(self, op, n_wires: int, has_params=False, trainable=False):
+        super().__init__()
+        self.n_wires = n_wires
+        self.op = op
+        self.ops_all = tq.QuantumModuleList()
+        for k in range(n_wires):
+            self.ops_all.append(op(has_params=has_params, trainable=trainable))
+
+    @tq.static_support
+    def forward(self, q_device):
+        for k in range(self.n_wires):
+            self.ops_all[k](q_device, wires=k)
+
+
+class Op2QAllLayer(tq.QuantumModule):
+    """
+        Quantum layer applying the same two-qubit operation to all pairs of adjacent wires.
+        This class represents a quantum layer that applies the same two-qubit operation to all pairs of adjacent wires
+        in the quantum device. The pairs of wires can be determined in a circular or non-circular pattern based on the
+        specified jump.
+
+        Args:
+            op (tq.Operator): Two-qubit operation to be applied.
+            n_wires (int): Number of wires in the quantum device.
+            has_params (bool, optional): Flag indicating if the operation has parameters. Defaults to False.
+            trainable (bool, optional): Flag indicating if the operation is trainable. Defaults to False.
+            wire_reverse (bool, optional): Flag indicating if the order of wires in each pair should be reversed. Defaults to False.
+            jump (int, optional): Number of positions to jump between adjacent pairs of wires. Defaults to 1.
+            circular (bool, optional): Flag indicating if the pattern should be circular. Defaults to False.
+
+    """
+    """pattern:
+    circular = False
+    jump = 1: [0, 1], [1, 2], [2, 3], [3, 4], [4, 5]
+    jump = 2: [0, 2], [1, 3], [2, 4], [3, 5]
+    jump = 3: [0, 3], [1, 4], [2, 5]
+    jump = 4: [0, 4], [1, 5]
+    jump = 5: [0, 5]
+
+    circular = True
+    jump = 1: [0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0]
+    jump = 2: [0, 2], [1, 3], [2, 4], [3, 5], [4, 0], [5, 1]
+    jump = 3: [0, 3], [1, 4], [2, 5], [3, 0], [4, 1], [5, 2]
+    jump = 4: [0, 4], [1, 5], [2, 0], [3, 1], [4, 2], [5, 3]
+    jump = 5: [0, 5], [1, 0], [2, 1], [3, 2], [4, 3], [5, 4]
+    """
+
+    def __init__(
+        self,
+        op,
+        n_wires: int,
+        has_params=False,
+        trainable=False,
+        wire_reverse=False,
+        jump=1,
+        circular=False,
+    ):
+        super().__init__()
+        self.n_wires = n_wires
+        self.jump = jump
+        self.circular = circular
+        self.op = op
+        self.ops_all = tq.QuantumModuleList()
+
+        # reverse the wires, for example from [1, 2] to [2, 1]
+        self.wire_reverse = wire_reverse
+
+        if circular:
+            n_ops = n_wires
+        else:
+            n_ops = n_wires - jump
+        for k in range(n_ops):
+            self.ops_all.append(op(has_params=has_params, trainable=trainable))
+
+    @tq.static_support
+    def forward(self, q_device):
+        for k in range(len(self.ops_all)):
+            wires = [k, (k + self.jump) % self.n_wires]
+            if self.wire_reverse:
+                wires.reverse()
+            self.ops_all[k](q_device, wires=wires)
+
+
+class Op2QFit32Layer(tq.QuantumModule):
+    """
+        Quantum layer applying the same two-qubit operation to all pairs of adjacent wires, fitting to 32 operations.
+
+        This class represents a quantum layer that applies the same two-qubit operation to all pairs of adjacent wires in the quantum device. The pairs of wires can be determined in a circular or non-circular pattern based on the specified jump. The layer is designed to fit to 32 operations by repeating the same operation pattern multiple times.
+
+        Args:
+            op (tq.Operator): Two-qubit operation to be applied.
+            n_wires (int): Number of wires in the quantum device.
+            has_params (bool, optional): Flag indicating if the operation has parameters. Defaults to False.
+            trainable (bool, optional): Flag indicating if the operation is trainable. Defaults to False.
+            wire_reverse (bool, optional): Flag indicating if the order of wires in each pair should be reversed. Defaults to False.
+            jump (int, optional): Number of positions to jump between adjacent pairs of wires. Defaults to 1.
+            circular (bool, optional): Flag indicating if the pattern should be circular. Defaults to False.
+
+        """
+    def __init__(
+        self,
+        op,
+        n_wires: int,
+        has_params=False,
+        trainable=False,
+        wire_reverse=False,
+        jump=1,
+        circular=False,
+    ):
+        super().__init__()
+        self.n_wires = n_wires
+        self.jump = jump
+        self.circular = circular
+        self.op = op
+        self.ops_all = tq.QuantumModuleList()
+
+        # reverse the wires, for example from [1, 2] to [2, 1]
+        self.wire_reverse = wire_reverse
+
+        # if circular:
+        #     n_ops = n_wires
+        # else:
+        #     n_ops = n_wires - jump
+        n_ops = 32
+        for k in range(n_ops):
+            self.ops_all.append(op(has_params=has_params, trainable=trainable))
+
+    @tq.static_support
+    def forward(self, q_device):
+        for k in range(len(self.ops_all)):
+            wires = [k % self.n_wires, (k + self.jump) % self.n_wires]
+            if self.wire_reverse:
+                wires.reverse()
+            self.ops_all[k](q_device, wires=wires)
+
+
+class Op2QButterflyLayer(tq.QuantumModule):
+    """
+        Quantum layer applying the same two-qubit operation in a butterfly pattern.
+
+        This class represents a quantum layer that applies the same two-qubit operation in a butterfly pattern. The butterfly pattern connects the first and last wire, the second and second-to-last wire, and so on, until the center wire(s) in the case of an odd number of wires.
+
+        Args:
+            op (tq.Operator): Two-qubit operation to be applied.
+            n_wires (int): Number of wires in the quantum device.
+            has_params (bool, optional): Flag indicating if the operation has parameters. Defaults to False.
+            trainable (bool, optional): Flag indicating if the operation is trainable. Defaults to False.
+            wire_reverse (bool, optional): Flag indicating if the order of wires in each pair should be reversed. Defaults to False.
+
+        """
+    """pattern: [0, 5], [1, 4], [2, 3]"""
+
+    def __init__(
+        self, op, n_wires: int, has_params=False, trainable=False, wire_reverse=False
+    ):
+        super().__init__()
+        self.n_wires = n_wires
+        self.op = op
+        self.ops_all = tq.QuantumModuleList()
+
+        # reverse the wires, for example from [1, 2] to [2, 1]
+        self.wire_reverse = wire_reverse
+
+        for k in range(n_wires // 2):
+            self.ops_all.append(op(has_params=has_params, trainable=trainable))
+
+    def forward(self, q_device):
+        for k in range(len(self.ops_all)):
+            wires = [k, self.n_wires - 1 - k]
+            if self.wire_reverse:
+                wires.reverse()
+            self.ops_all[k](q_device, wires=wires)
+
+
+class Op2QDenseLayer(tq.QuantumModule):
+    """
+       Quantum layer applying the same two-qubit operation in a dense pattern.
+
+       This class represents a quantum layer that applies the same two-qubit operation in a dense pattern. The dense pattern connects every pair of wires, ensuring that each wire is connected to every other wire exactly once.
+
+       Args:
+           op (tq.Operator): Two-qubit operation to be applied.
+           n_wires (int): Number of wires in the quantum device.
+           has_params (bool, optional): Flag indicating if the operation has parameters. Defaults to False.
+           trainable (bool, optional): Flag indicating if the operation is trainable. Defaults to False.
+           wire_reverse (bool, optional): Flag indicating if the order of wires in each pair should be reversed. Defaults to False.
+
+       """
+    """pattern:
+    [0, 1], [0, 2], [0, 3], [0, 4], [0, 5]
+    [1, 2], [1, 3], [1, 4], [1, 5]
+    [2, 3], [2, 4], [2, 5]
+    [3, 4], [3, 5]
+    [4, 5]
+    """
+
+    def __init__(
+        self, op, n_wires: int, has_params=False, trainable=False, wire_reverse=False
+    ):
+        super().__init__()
+        self.n_wires = n_wires
+        self.op = op
+        self.ops_all = tq.QuantumModuleList()
+
+        # reverse the wires, for example from [1, 2] to [2, 1]
+        self.wire_reverse = wire_reverse
+
+        for k in range(self.n_wires * (self.n_wires - 1) // 2):
+            self.ops_all.append(op(has_params=has_params, trainable=trainable))
+
+    def forward(self, q_device):
+        k = 0
+        for i in range(self.n_wires - 1):
+            for j in range(i + 1, self.n_wires):
+                wires = [i, j]
+                if self.wire_reverse:
+                    wires.reverse()
+                self.ops_all[k](q_device, wires=wires)
+                k += 1
+
+
+class LayerTemplate0(tq.QuantumModule):
+    """
+       A template for a custom quantum layer.
+
+       Args:
+           arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+       Attributes:
+           n_wires (int): The number of wires in the layer.
+           arch (dict): The architecture configuration for the layer.
+           n_blocks (int): The number of blocks in the layer. (Optional)
+           n_layers_per_block (int): The number of layers per block. (Optional)
+           layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+       Methods:
+           build_layers: Abstract method to build the layers of the template.
+           forward: Applies the quantum layer to the given quantum device.
+
+       """
+    def __init__(self, arch: dict = None):
+        super().__init__()
+        self.n_wires = arch["n_wires"]
+        self.arch = arch
+
+        self.n_blocks = arch.get("n_blocks", None)
+        self.n_layers_per_block = arch.get("n_layers_per_block", None)
+
+        self.layers_all = self.build_layers()
+
+    def build_layers(self):
+        raise NotImplementedError
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice):
+        self.q_device = q_device
+        for k in range(len(self.layers_all)):
+            self.layers_all[k](q_device)
+
+
+class U3CU3Layer0(LayerTemplate0):
+    """
+        Layer template with U3 and CU3 blocks.
+
+        This layer template consists of U3 and CU3 blocks repeated for the specified number of blocks.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the U3 and CU3 layers for the template.
+            forward: Applies the quantum layer to the given quantum device.
+
+        """
+
+
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.U3, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.CU3,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+        return layers_all
+
+
+class CU3Layer0(LayerTemplate0):
+    """
+        Layer template with CU3 blocks.
+
+        This layer template consists of CU3 blocks repeated for the specified number of blocks.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the CU3 layers for the template.
+            forward: Applies the quantum layer to the given quantum device.
+
+        """
+
+
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.CU3,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=False,
+                )
+            )
+        return layers_all
+
+
+class CXRZSXLayer0(LayerTemplate0):
+    """
+        Layer template with CXRZSX blocks.
+
+        This layer template consists of CXRZSX blocks, which include RZ, CNOT, and SX gates, repeated for the specified number of blocks.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the CXRZSX layers for the template.
+            forward: Applies the quantum layer to the given quantum device.
+
+        """
+
+
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+
+        layers_all.append(
+            Op1QAllLayer(
+                op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
+            )
+        )
+        layers_all.append(
+            Op2QAllLayer(op=tq.CNOT, n_wires=self.n_wires, jump=1, circular=False)
+        )
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.SX, n_wires=self.n_wires, has_params=False, trainable=False
+                )
+            )
+        layers_all.append(
+            Op1QAllLayer(
+                op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
+            )
+        )
+        return layers_all
+
+
+class SethLayer0(LayerTemplate0):
+    """
+        Layer template with Seth blocks.
+
+        This layer template consists of Seth blocks, which include RZZ and RY gates, repeated for the specified number of blocks.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the Seth layers for the template.
+            forward: Applies the quantum layer to the given quantum device.
+
+        """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.RZZ,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+        return layers_all
+
+
+class SethLayer1(LayerTemplate0):
+    """
+       Layer template with extended Seth blocks.
+
+       This layer template consists of extended Seth blocks, which include RZZ and RY gates repeated twice for each block.
+
+       Args:
+           arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+       Attributes:
+           n_wires (int): The number of wires in the layer.
+           arch (dict): The architecture configuration for the layer.
+           n_blocks (int): The number of blocks in the layer.
+           layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+       Methods:
+           build_layers: Builds the extended Seth layers for the template.
+           forward: Applies the quantum layer to the given quantum device.
+
+       """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.RZZ,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.RZZ,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+        return layers_all
+
+
+class SethLayer2(LayerTemplate0):
+    """
+        Layer template with Seth blocks using Op2QFit32Layer.
+
+        This layer template consists of Seth blocks using the Op2QFit32Layer, which includes RZZ gates and supports 32 wires.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the Seth layers with Op2QFit32Layer for the template.
+            forward: Applies the quantum layer to the given quantum device.
+
+        """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op2QFit32Layer(
+                    op=tq.RZZ,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+        return layers_all
+
+
+class RZZLayer0(LayerTemplate0):
+    """
+        Layer template with RZZ blocks.
+
+        This layer template consists of RZZ blocks using the Op2QAllLayer.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the RZZ layers with Op2QAllLayer for the template.
+            forward: Applies the quantum layer to the given quantum device.
+
+        """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.RZZ,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+        return layers_all
+
+
+class BarrenLayer0(LayerTemplate0):
+    """
+        Layer template with Barren blocks.
+
+        This layer template consists of Barren blocks using the Op1QAllLayer and Op2QAllLayer.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the Barren layers with Op1QAllLayer and Op2QAllLayer for the template.
+            forward: Applies the quantum layer to the given quantum device.
+
+        """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        layers_all.append(
+            Op1QAllLayer(
+                op=tq.SHadamard,
+                n_wires=self.n_wires,
+            )
+        )
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RX, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(Op2QAllLayer(op=tq.CZ, n_wires=self.n_wires, jump=1))
+        return layers_all
+
+
+class FarhiLayer0(LayerTemplate0):
+    """
+     Layer template with Farhi blocks.
+
+     This layer template consists of Farhi blocks using the Op2QAllLayer.
+
+     Args:
+         arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+     Attributes:
+         n_wires (int): The number of wires in the layer.
+         arch (dict): The architecture configuration for the layer.
+         n_blocks (int): The number of blocks in the layer.
+         layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+     Methods:
+         build_layers: Builds the Farhi layers with Op2QAllLayer for the template.
+         forward: Applies the quantum layer to the given quantum device.
+
+     """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.RZX,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.RXX,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+        return layers_all
+
+
+class MaxwellLayer0(LayerTemplate0):
+    """
+       Layer template with Maxwell blocks.
+
+       This layer template consists of Maxwell blocks using the Op1QAllLayer and Op2QAllLayer modules.
+
+       Args:
+           arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+       Attributes:
+           n_wires (int): The number of wires in the layer.
+           arch (dict): The architecture configuration for the layer.
+           n_blocks (int): The number of blocks in the layer.
+           layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+       Methods:
+           build_layers: Builds the Maxwell layers with Op1QAllLayer and Op2QAllLayer for the template.
+           forward: Applies the quantum layer to the given quantum device.
+
+       """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RX, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(Op1QAllLayer(op=tq.S, n_wires=self.n_wires))
+            layers_all.append(
+                Op2QAllLayer(op=tq.CNOT, n_wires=self.n_wires, jump=1, circular=True)
+            )
+
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(Op1QAllLayer(op=tq.T, n_wires=self.n_wires))
+            layers_all.append(
+                Op2QAllLayer(op=tq.SWAP, n_wires=self.n_wires, jump=1, circular=True)
+            )
+
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(Op1QAllLayer(op=tq.Hadamard, n_wires=self.n_wires))
+            layers_all.append(
+                Op2QAllLayer(op=tq.SSWAP, n_wires=self.n_wires, jump=1, circular=True)
+            )
+
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.U1, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op2QAllLayer(
+                    op=tq.CU3,
+                    n_wires=self.n_wires,
+                    has_params=True,
+                    trainable=True,
+                    jump=1,
+                    circular=True,
+                )
+            )
+
+        return layers_all
+
+
+class RYRYCXLayer0(LayerTemplate0):
+    """
+       Layer template with RYRYCX blocks.
+
+       This layer template consists of RYRYCX blocks using the Op1QAllLayer and CXLayer modules.
+
+       Args:
+           arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+       Attributes:
+           n_wires (int): The number of wires in the layer.
+           arch (dict): The architecture configuration for the layer.
+           n_blocks (int): The number of blocks in the layer.
+           layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+       Methods:
+           build_layers: Builds the RYRYCX layers with Op1QAllLayer and CXLayer for the template.
+           forward: Applies the quantum layer to the given quantum device.
+
+       """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(CXLayer(n_wires=self.n_wires))
+        return layers_all
+
+
+class RYRYRYCXCXCXLayer0(LayerTemplate0):
+    """
+       Layer template with RYRYRYCXCXCX blocks.
+
+       This layer template consists of RYRYRYCXCXCX blocks using the RYRYCXCXLayer module.
+
+       Args:
+           arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+       Attributes:
+           n_wires (int): The number of wires in the layer.
+           arch (dict): The architecture configuration for the layer.
+           n_blocks (int): The number of blocks in the layer.
+           layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+       Methods:
+           build_layers: Builds the RYRYRYCXCXCX layers with RYRYCXCXLayer for the template.
+
+       """
+
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(CXCXCXLayer(n_wires=self.n_wires))
+        return layers_all
+
+
+class RYRYRYLayer0(LayerTemplate0):
+    """
+        Layer template with RYRYRYCXCXCX blocks.
+
+        This layer template consists of RYRYRYCXCXCX blocks using the Op1QAllLayer and CXCXCXLayer modules.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the RYRYRYCXCXCX layers with Op1QAllLayer and CXCXCXLayer for the template.
+
+
+        """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+        return layers_all
+
+
+class RYRYRYSWAPSWAPLayer0(LayerTemplate0):
+    """
+        Layer template with RYRYRYSWAPSWAP blocks.
+
+        This layer template consists of RYRYRYSWAPSWAP blocks using the Op1QAllLayer and SWAPSWAPLayer modules.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the RYRYRYSWAPSWAP layers with Op1QAllLayer and SWAPSWAPLayer for the template.
+
+
+        """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(SWAPSWAPLayer(n_wires=self.n_wires))
+        return layers_all
+
+
+class SWAPSWAPLayer0(LayerTemplate0):
+    """
+        Layer template with SWAPSWAP blocks.
+
+        This layer template consists of SWAPSWAP blocks using the SWAPSWAPLayer module.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the SWAPSWAP layers with SWAPSWAPLayer for the template.
+
+        """
+
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(SWAPSWAPLayer(n_wires=self.n_wires))
+        return layers_all
+
+
+class RXYZCXLayer0(LayerTemplate0):
+    """
+        Layer template with RXYZCX blocks.
+
+        This layer template consists of RXYZCX blocks using the RXYZCXLayer module.
+
+        Args:
+            arch (dict, optional): The architecture configuration for the layer. Defaults to None.
+
+        Attributes:
+            n_wires (int): The number of wires in the layer.
+            arch (dict): The architecture configuration for the layer.
+            n_blocks (int): The number of blocks in the layer.
+            layers_all (tq.QuantumModuleList): The list of layers in the template.
+
+        Methods:
+            build_layers: Builds the RXYZCX layers with RXYZCXLayer for the template.
+
+        """
+    def build_layers(self):
+        layers_all = tq.QuantumModuleList()
+        for k in range(self.arch["n_blocks"]):
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RX, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op1QAllLayer(
+                    op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
+                )
+            )
+            layers_all.append(
+                Op2QAllLayer(op=tq.CNOT, n_wires=self.n_wires, jump=1, circular=True)
+            )
+        return layers_all
+
+
+class QFTLayer(tq.QuantumModule):
+    def __init__(
+        self,
+        n_wires: int = None,
+        wires: Iterable = None,
+        do_swaps: bool = True,
+        inverse: bool = False,
+    ):
+        """
+        Constructs a Quantum Fourier Transform (QFT) layer
+
+        Args:
+            n_wires (int): Number of wires for the QFT as an integer
+            wires (Iterable): Wires to perform the QFT as an Iterable
+            do_swaps (bool): Whether or not to add the final swaps in a boolean format
+            inverse (bool): Whether to create an inverse QFT layer in a boolean format
+        """
+        super().__init__()
+
+        assert n_wires is not None or wires is not None
+
+        if n_wires is None:
+            self.n_wires = len(wires)
+
+        if wires is None:
+            wires = range(n_wires)
+
+        self.n_wires = n_wires
+        self.wires = wires
+        self.do_swaps = do_swaps
+
+        if inverse:
+            self.gates_all = self.build_inverse_circuit()
+        else:
+            self.gates_all = self.build_circuit()
+
+    def build_circuit(self):
+        """Construct a QFT circuit."""
+
+        operation_list = []
+
+        # add the H and CU1 gates
+        for top_wire in range(self.n_wires):
+            operation_list.append({"name": "hadamard", "wires": self.wires[top_wire]})
+            for wire in range(top_wire + 1, self.n_wires):
+                lam = torch.pi / (2 ** (wire - top_wire))
+                operation_list.append(
+                    {
+                        "name": "cu1",
+                        "params": lam,
+                        "wires": [self.wires[wire], self.wires[top_wire]],
+                    }
+                )
+
+        # add swaps if specified
+        if self.do_swaps:
+            for wire in range(self.n_wires // 2):
+                operation_list.append(
+                    {
+                        "name": "swap",
+                        "wires": [
+                            self.wires[wire],
+                            self.wires[self.n_wires - wire - 1],
+                        ],
+                    }
+                )
+
+        return tq.QuantumModule.from_op_history(operation_list)
+
+    def build_inverse_circuit(self):
+        """Construct the inverse of a QFT circuit."""
+
+        operation_list = []
+
+        # add swaps if specified
+        if self.do_swaps:
+            for wire in range(self.n_wires // 2):
+                operation_list.append(
+                    {
+                        "name": "swap",
+                        "wires": [
+                            self.wires[wire],
+                            self.wires[self.n_wires - wire - 1],
+                        ],
+                    }
+                )
+
+        # add the CU1 and H gates
+        for top_wire in range(self.n_wires)[::-1]:
+            for wire in range(top_wire + 1, self.n_wires)[::-1]:
+                lam = -torch.pi / (2 ** (wire - top_wire))
+                operation_list.append(
+                    {
+                        "name": "cu1",
+                        "params": lam,
+                        "wires": [self.wires[wire], self.wires[top_wire]],
+                    }
+                )
+            operation_list.append({"name": "hadamard", "wires": self.wires[top_wire]})
+
+        return tq.QuantumModule.from_op_history(operation_list)
+
+    @tq.static_support
+    def forward(self, q_device: tq.QuantumDevice):
+        self.gates_all(q_device)
+
+
+layer_name_dict = {
+    "u3cu3_0": U3CU3Layer0,
+    "cu3_0": CU3Layer0,
+    "cxrzsx_0": CXRZSXLayer0,
+    "seth_0": SethLayer0,
+    "seth_1": SethLayer1,
+    "seth_2": SethLayer2,
+    "rzz_0": RZZLayer0,
+    "barren_0": BarrenLayer0,
+    "farhi_0": FarhiLayer0,
+    "maxwell_0": MaxwellLayer0,
+    "ryrycx": RYRYCXLayer0,
+    "ryryrycxcxcx": RYRYRYCXCXCXLayer0,
+    "ryryry": RYRYRYLayer0,
+    "swapswap": SWAPSWAPLayer0,
+    "ryryryswapswap": RYRYRYSWAPSWAPLayer0,
+    "rxyzcx_0": RXYZCXLayer0,
+}
diff --git a/torchquantum/layer/nlocal.py b/torchquantum/layer/nlocal.py
new file mode 100644
index 00000000..1a3c8803
--- /dev/null
+++ b/torchquantum/layer/nlocal.py
@@ -0,0 +1,324 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+
+import torch
+import torchquantum as tq
+from torchquantum.layer.layers import (
+    LayerTemplate0,
+    Op1QAllLayer,
+    Op2QAllLayer,
+    RandomOp1All,
+)
+
+__all__ = [
+    "NLocal",
+    "TwoLocal",
+    "ExcitationPreserving",
+    "EfficientSU2",
+    "RealAmplitudes",
+    "PauliTwoDesign",
+]
+
+
+class NLocal(LayerTemplate0):
+    """Layer Template for a NLocal Class
+
+    Args:
+        rotation_ops (list): gates for the rotation layer as a list of torchquantum operations
+        entanglement_ops (list): gates for the entanglement layer as a list of torchquantum operations
+        arch (dict): circuit architecture in a dictionary format
+        rotation_layer (torchquantum.QuantumModule): type of rotation layer in a torchquantum.QuantumModule format
+        entanglement_layer (torchquantum.QuantumModule): type of entanglement layer in a torchquantum.QuantumModule format
+        reps (int): number of reptitions of the rotation and entanglement layers in a integer format
+        rotation_layer_params (dict): additional parameters for the rotation layer in a dictionary format
+        entanglement_layer_params (dict): additional parameters for the entanglement layer in a dictionary format
+        initial_circuit (torchquantum.QuantumModule): initial gates or layer in a QuantumModule format
+        skip_final_rotation_layer (bool): whether or not to add the final rotation layer as a boolean
+    """
+
+    def __init__(
+        self,
+        rotation_ops: list = None,
+        entanglement_ops: list = None,
+        arch: dict = None,
+        rotation_layer: tq.QuantumModule = Op1QAllLayer,
+        entanglement_layer: tq.QuantumModule = Op2QAllLayer,
+        reps: int = 1,
+        rotation_layer_params: dict = {},
+        entanglement_layer_params: dict = {},
+        initial_circuit: tq.QuantumModule = None,
+        skip_final_rotation_layer: bool = False,
+    ):
+        # rotation block options
+        self.rotation_ops = rotation_ops
+        self.rotation_layer = rotation_layer
+        self.rotation_layer_params = rotation_layer_params
+
+        # entanglement block options
+        self.entanglement_ops = entanglement_ops
+        self.entanglement_layer = entanglement_layer
+        self.entanglement_layer_params = entanglement_layer_params
+
+        # extra parameters
+        self.initial_circuit = initial_circuit
+        self.skip_final_rotation_layer = skip_final_rotation_layer
+        self.reps = reps
+
+        # initialize the LayerTemplate0
+        super().__init__(arch)
+
+    def build_initial_layer(self):
+        """Build the initial layer"""
+        return self.initial_circuit
+
+    def build_rotation_block(self):
+        """Build rotation block"""
+        rotation_layers = []
+        for rot in self.rotation_ops:
+            rotation_layers.append(
+                self.rotation_layer(
+                    op=rot, n_wires=self.n_wires, **self.rotation_layer_params
+                )
+            )
+        return rotation_layers
+
+    def build_entanglement_block(self):
+        """Build entanglement block"""
+        entanglement_layers = []
+        for entanglement in self.entanglement_ops:
+            entanglement_layers.append(
+                self.entanglement_layer(
+                    op=entanglement,
+                    n_wires=self.n_wires,
+                    **self.entanglement_layer_params,
+                )
+            )
+        return entanglement_layers
+
+    def build_layers(self):
+        """Build nlocal circuit"""
+        layers_all = tq.QuantumModuleList()
+
+        # add the initial circuit
+        initial_circuit = self.build_initial_layer()
+        if initial_circuit is not None:
+            layers_all.append(initial_circuit)
+
+        # repeat for each rep
+        for _ in range(self.reps):
+            # add rotation blocks to the qubits
+            layers_all.extend(self.build_rotation_block())
+
+            # add entanglement blocks to the qubits
+            layers_all.extend(self.build_entanglement_block())
+
+        # add final rotation layer
+        if not self.skip_final_rotation_layer:
+            layers_all.extend(self.build_rotation_block())
+
+        # return QuantumModuleList
+        return layers_all
+
+
+class TwoLocal(NLocal):
+    """Layer Template for a TwoLocal Class
+
+    Args:
+        rotation_ops (list): gates for the rotation layer as a list of torchquantum operations
+        entanglement_ops (list): gates for the entanglement layer as a list of torchquantum operations
+        arch (dict): circuit architecture in a dictionary format
+        rotation_layer (torchquantum.QuantumModule): type of rotation layer in a torchquantum.QuantumModule format
+        entanglement_layer (str): type of entanglement layer in a string ("linear", "reverse_linear", "circular", "full") or tq.QuantumModule format
+        reps (int): number of reptitions of the rotation and entanglement layers in a integer format
+        entanglement_layer_params (dict): additional parameters for the entanglement layer in a dictionary forma
+        initial_circuit (torchquantum.QuantumModule): initial gates or layer in a QuantumModule formatt
+        skip_final_rotation_layer (bool): whether or not to add the final rotation layer as a boolean
+    """
+
+    def __init__(
+        self,
+        rotation_ops: list = None,
+        entanglement_ops: list = None,
+        arch: dict = None,
+        rotation_layer: tq.QuantumModule = Op1QAllLayer,
+        entanglement_layer: str = "linear",
+        reps: int = 1,
+        entanglement_layer_params: dict = {},
+        initial_circuit: tq.QuantumModule = None,
+        skip_final_rotation_layer: bool = False,
+    ):
+        # if passed as string, determine entanglement type
+        if entanglement_layer == "linear":
+            entanglement_layer = Op2QAllLayer
+        elif entanglement_layer == "reverse_linear":
+            entanglement_layer = Op2QAllLayer
+            entanglement_layer_params = {"wire_reverse": True}
+        elif entanglement_layer == "circular":
+            entanglement_layer = Op2QAllLayer
+            entanglement_layer_params = {"circular": True}
+        elif entanglement_layer == "full":
+            entanglement_layer = Op2QDenseLayer
+
+        # initialize
+        super().__init__(
+            arch=arch,
+            rotation_ops=rotation_ops,
+            rotation_layer=rotation_layer,
+            rotation_layer_params={"has_params": True, "trainable": True},
+            entanglement_ops=entanglement_ops,
+            entanglement_layer=entanglement_layer,
+            entanglement_layer_params=entanglement_layer_params,
+            initial_circuit=initial_circuit,
+            reps=reps,
+            skip_final_rotation_layer=skip_final_rotation_layer,
+        )
+
+
+class ExcitationPreserving(TwoLocal):
+    """Layer Template for a ExcitationPreserving circuit
+
+    Args:
+        arch (dict): circuit architecture in a dictionary format
+        entanglement_layer (str): type of entanglement layer in a string ("linear", "reverse_linear", "circular", "full") or tq.QuantumModule format
+        reps (int): number of reptitions of the rotation and entanglement layers in a integer format
+        skip_final_rotation_layer (bool): whether or not to add the final rotation layer as a boolean
+    """
+
+    def __init__(
+        self,
+        arch: dict = None,
+        entanglement_layer: str = "full",
+        reps: int = 3,
+        skip_final_rotation_layer: bool = False,
+    ):
+        # construct circuit with rotation layers of RZ and entanglement with RXX and RYY
+        super().__init__(
+            arch=arch,
+            rotation_ops=[tq.RZ],
+            entanglement_ops=[tq.RXX, tq.RYY],
+            entanglement_layer=entanglement_layer,
+            entanglement_layer_params={"has_params": True, "trainable": True},
+            reps=reps,
+            skip_final_rotation_layer=skip_final_rotation_layer,
+        )
+
+
+class EfficientSU2(TwoLocal):
+    """Layer Template for a EfficientSU2 circuit
+
+    Args:
+        arch (dict): circuit architecture in a dictionary format
+        entanglement_layer (str): type of entanglement layer in a string ("linear", "reverse_linear", "circular", "full") or tq.QuantumModule format
+        reps (int): number of reptitions of the rotation and entanglement layers in a integer format
+        skip_final_rotation_layer (bool): whether or not to add the final rotation layer as a boolean
+    """
+
+    def __init__(
+        self,
+        arch: dict = None,
+        entanglement_layer: str = "reverse_linear",
+        reps: int = 3,
+        skip_final_rotation_layer: bool = False,
+    ):
+        # construct circuit with rotation layers of RY and RZ and entanglement with CX
+        super().__init__(
+            arch=arch,
+            rotation_ops=[tq.RY, tq.RZ],
+            entanglement_ops=[tq.CNOT],
+            entanglement_layer=entanglement_layer,
+            reps=reps,
+            skip_final_rotation_layer=skip_final_rotation_layer,
+        )
+
+
+class RealAmplitudes(TwoLocal):
+    """Layer Template for a RealAmplitudes circuit
+
+    Args:
+        arch (dict): circuit architecture in a dictionary format
+        entanglement_layer (str): type of entanglement layer in a string ("linear", "reverse_linear", "circular", "full") or tq.QuantumModule format
+        reps (int): number of reptitions of the rotation and entanglement layers in a integer format
+        skip_final_rotation_layer (bool): whether or not to add the final rotation layer as a boolean
+    """
+
+    def __init__(
+        self,
+        arch: dict = None,
+        entanglement_layer: str = "reverse_linear",
+        reps: int = 3,
+        skip_final_rotation_layer: bool = False,
+    ):
+        # construct circuit with rotation layers of RY and entanglement with CX
+        super().__init__(
+            arch=arch,
+            rotation_ops=[tq.RY],
+            entanglement_ops=[tq.CNOT],
+            entanglement_layer=entanglement_layer,
+            reps=reps,
+            skip_final_rotation_layer=skip_final_rotation_layer,
+        )
+
+
+class PauliTwoDesign(TwoLocal):
+    """Layer Template for a PauliTwoDesign circuit
+
+    Args:
+        arch (dict): circuit architecture in a dictionary format
+        entanglement_layer (str): type of entanglement layer in a string ("linear", "reverse_linear", "circular", "full") or tq.QuantumModule format
+        reps (int): number of reptitions of the rotation and entanglement layers in a integer format
+        skip_final_rotation_layer (bool): whether or not to add the final rotation layer as a boolean
+    """
+
+    def __init__(
+        self,
+        arch: dict = None,
+        entanglement_layer: str = "reverse_linear",
+        reps: int = 3,
+        skip_final_rotation_layer: bool = False,
+        seed: int = 0,
+    ):
+        # set seed
+        self.seed = seed
+        # construct circuit with entanglement with CX
+        super().__init__(
+            arch=arch,
+            entanglement_ops=[tq.CNOT],
+            entanglement_layer=entanglement_layer,
+            reps=reps,
+            skip_final_rotation_layer=skip_final_rotation_layer,
+        )
+
+    def build_initial_layer(self):
+        # add an initial layer of ry with rotation pi/4
+        return tq.QuantumModule.from_op_history(
+            [
+                {"name": "ry", "wires": wire, "params": torch.pi / 4}
+                for wire in range(self.arch["n_wires"])
+            ]
+        )
+
+    def build_rotation_block(self):
+        # make a random layer of rotations
+        return [RandomOp1All(n_wires=self.n_wires, seed=self.seed)]
diff --git a/torchquantum/layers.py b/torchquantum/layers.py
deleted file mode 100644
index 12f35431..00000000
--- a/torchquantum/layers.py
+++ /dev/null
@@ -1,910 +0,0 @@
-import torch.nn as nn
-import torchquantum as tq
-import torchquantum.functional as tqf
-import numpy as np
-
-
-from typing import Iterable
-from torchquantum.plugins.qiskit_macros import QISKIT_INCOMPATIBLE_FUNC_NAMES
-from torchpack.utils.logging import logger
-
-__all__ = [
-    "QuantumModuleFromOps",
-    "TrainableOpAll",
-    "ClassicalInOpAll",
-    "FixedOpAll",
-    "TwoQAll",
-    "RandomLayer",
-    "RandomLayerAllTypes",
-    "Op1QAllLayer",
-    "Op2QAllLayer",
-    "Op2QButterflyLayer",
-    "Op2QDenseLayer",
-    "layer_name_dict",
-    "CXLayer",
-    "CXCXCXLayer",
-    "SWAPSWAPLayer",
-    "RXYZCXLayer0",
-]
-
-
-class QuantumModuleFromOps(tq.QuantumModule):
-    def __init__(self, ops):
-        super().__init__()
-        self.ops = tq.QuantumModuleList(ops)
-
-    @tq.static_support
-    def forward(self, q_device: tq.QuantumDevice):
-        self.q_device = q_device
-        for op in self.ops:
-            op(q_device)
-
-
-class TrainableOpAll(tq.QuantumModule):
-    """Rotation rx on all qubits
-    The rotation angle is a parameter of each rotation gate
-    One potential optimization is to compute the unitary of all gates
-    together.
-    """
-
-    def __init__(self, n_gate: int, op: tq.Operation):
-        super().__init__()
-        self.n_gate = n_gate
-        self.gate_all = nn.ModuleList()
-        for k in range(self.n_gate):
-            self.gate_all.append(op(has_params=True, trainable=True))
-
-    @tq.static_support
-    def forward(self, q_device: tq.QuantumDevice):
-        # rx on all wires, assert the number of gate is the same as the number
-        # of wires in the device.
-        assert self.n_gate == q_device.n_wires, (
-            f"Number of rx gates ({self.n_gate}) is different from number "
-            f"of wires ({q_device.n_wires})!"
-        )
-
-        for k in range(self.n_gate):
-            self.gate_all[k](q_device, wires=k)
-
-
-class ClassicalInOpAll(tq.QuantumModule):
-    def __init__(self, n_gate: int, op: tq.Operator):
-        super().__init__()
-        self.n_gate = n_gate
-        self.gate_all = nn.ModuleList()
-        for k in range(self.n_gate):
-            self.gate_all.append(op())
-
-    @tq.static_support
-    def forward(self, q_device: tq.QuantumDevice, x):
-        # rx on all wires, assert the number of gate is the same as the number
-        # of wires in the device.
-        assert self.n_gate == q_device.n_wires, (
-            f"Number of rx gates ({self.n_gate}) is different from number "
-            f"of wires ({q_device.n_wires})!"
-        )
-
-        for k in range(self.n_gate):
-            self.gate_all[k](q_device, wires=k, params=x[:, k])
-
-
-class FixedOpAll(tq.QuantumModule):
-    def __init__(self, n_gate: int, op: tq.Operator):
-        super().__init__()
-        self.n_gate = n_gate
-        self.gate_all = nn.ModuleList()
-        for k in range(self.n_gate):
-            self.gate_all.append(op())
-
-    @tq.static_support
-    def forward(self, q_device: tq.QuantumDevice):
-        # rx on all wires, assert the number of gate is the same as the number
-        # of wires in the device.
-        assert self.n_gate == q_device.n_wires, (
-            f"Number of rx gates ({self.n_gate}) is different from number "
-            f"of wires ({q_device.n_wires})!"
-        )
-
-        for k in range(self.n_gate):
-            self.gate_all[k](q_device, wires=k)
-
-
-class TwoQAll(tq.QuantumModule):
-    def __init__(self, n_gate: int, op: tq.Operator):
-        super().__init__()
-        self.n_gate = n_gate
-        self.op = op()
-
-    @tq.static_support
-    def forward(self, q_device: tq.QuantumDevice):
-        for k in range(self.n_gate - 1):
-            self.op(q_device, wires=[k, k + 1])
-        self.op(q_device, wires=[self.n_gate - 1, 0])
-
-
-class RandomLayer(tq.QuantumModule):
-    def __init__(
-        self,
-        wires,
-        n_ops=None,
-        n_params=None,
-        op_ratios=None,
-        op_types=(tq.RX, tq.RY, tq.RZ, tq.CNOT),
-        seed=None,
-        qiskit_compatible=False,
-    ):
-        super().__init__()
-        self.n_ops = n_ops
-        self.n_params = n_params
-        assert n_params is not None or n_ops is not None
-        self.wires = wires if isinstance(wires, Iterable) else [wires]
-        self.n_wires = len(wires)
-
-        op_types = op_types if isinstance(op_types, Iterable) else [op_types]
-        if op_ratios is None:
-            op_ratios = [1] * len(op_types)
-        else:
-            op_ratios = op_ratios if isinstance(op_ratios, Iterable) else [op_ratios]
-        op_types_valid = []
-        op_ratios_valid = []
-
-        if qiskit_compatible:
-            for op_type, op_ratio in zip(op_types, op_ratios):
-                if op_type().name.lower() in QISKIT_INCOMPATIBLE_FUNC_NAMES:
-                    logger.warning(
-                        f"Remove {op_type} from op_types to make "
-                        f"the layer qiskit-compatible."
-                    )
-                else:
-                    op_types_valid.append(op_type)
-                    op_ratios_valid.append(op_ratio)
-        else:
-            op_types_valid = op_types
-            op_ratios_valid = op_ratios
-
-        self.op_types = op_types_valid
-        self.op_ratios = np.array(op_ratios_valid) / sum(op_ratios_valid)
-
-        self.seed = seed
-        self.op_list = tq.QuantumModuleList()
-        if seed is not None:
-            np.random.seed(seed)
-        self.build_random_layer()
-
-    def rebuild_random_layer_from_op_list(self, n_ops_in, wires_in, op_list_in):
-        """Used for loading random layer from checkpoint"""
-        self.n_ops = n_ops_in
-        self.wires = wires_in
-        self.op_list = tq.QuantumModuleList()
-        for op_in in op_list_in:
-            op = tq.op_name_dict[op_in.name.lower()](
-                has_params=op_in.has_params,
-                trainable=op_in.trainable,
-                wires=op_in.wires,
-                n_wires=op_in.n_wires,
-            )
-            self.op_list.append(op)
-
-    def build_random_layer(self):
-        op_cnt = 0
-        param_cnt = 0
-        while True:
-            op = np.random.choice(self.op_types, p=self.op_ratios)
-            n_op_wires = op.num_wires
-            if n_op_wires > self.n_wires:
-                continue
-            if n_op_wires == -1:
-                is_AnyWire = True
-                n_op_wires = self.n_wires
-            else:
-                is_AnyWire = False
-
-            op_wires = list(
-                np.random.choice(self.wires, size=n_op_wires, replace=False)
-            )
-            if is_AnyWire:
-                if op().name in ["MultiRZ"]:
-                    operation = op(
-                        has_params=True,
-                        trainable=True,
-                        n_wires=n_op_wires,
-                        wires=op_wires,
-                    )
-                else:
-                    operation = op(n_wires=n_op_wires, wires=op_wires)
-            elif op().name in tq.Operator.parameterized_ops:
-                operation = op(has_params=True, trainable=True, wires=op_wires)
-            else:
-                operation = op(wires=op_wires)
-            self.op_list.append(operation)
-            op_cnt += 1
-            param_cnt += op.num_params
-
-            if self.n_ops is not None and op_cnt == self.n_ops:
-                break
-            elif self.n_ops is None and self.n_params is not None:
-                if param_cnt == self.n_params:
-                    break
-                elif param_cnt > self.n_params:
-                    """
-                    the last operation has too many params and exceed the
-                    constraint, so need to remove it and sample another
-                    """
-                    op_cnt -= 1
-                    param_cnt -= op.num_params
-                    del self.op_list[-1]
-
-    @tq.static_support
-    def forward(self, q_device: tq.QuantumDevice):
-        for op in self.op_list:
-            op(q_device)
-
-
-class RandomLayerAllTypes(RandomLayer):
-    def __init__(
-        self,
-        wires,
-        n_ops=None,
-        n_params=None,
-        op_ratios=None,
-        op_types=(
-            tq.Hadamard,
-            tq.SHadamard,
-            tq.PauliX,
-            tq.PauliY,
-            tq.PauliZ,
-            tq.S,
-            tq.T,
-            tq.SX,
-            tq.CNOT,
-            tq.CZ,
-            tq.CY,
-            tq.RX,
-            tq.RY,
-            tq.RZ,
-            tq.RZZ,
-            tq.SWAP,
-            tq.CSWAP,
-            tq.Toffoli,
-            tq.PhaseShift,
-            tq.Rot,
-            tq.MultiRZ,
-            tq.CRX,
-            tq.CRY,
-            tq.CRZ,
-            tq.CRot,
-            tq.U1,
-            tq.U2,
-            tq.U3,
-            tq.MultiCNOT,
-            tq.MultiXCNOT,
-        ),
-        seed=None,
-        qiskit_compatible=False,
-    ):
-        super().__init__(
-            wires=wires,
-            n_ops=n_ops,
-            n_params=n_params,
-            op_ratios=op_ratios,
-            op_types=op_types,
-            seed=seed,
-            qiskit_compatible=qiskit_compatible,
-        )
-
-
-class SimpleQLayer(tq.QuantumModule):
-    def __init__(self, n_wires):
-        super().__init__()
-        self.n_wires = n_wires
-        self.gate1 = tq.RX(has_params=True, trainable=True)
-        self.gate2 = tq.RY(has_params=True, trainable=True)
-        self.gate3 = tq.RZ(has_params=True, trainable=True)
-
-    @tq.static_support
-    def forward(self, q_dev):
-        self.q_device = q_dev
-        tqf.x(q_dev, wires=0, static=self.static_mode, parent_graph=self.graph)
-        self.gate1(q_dev, wires=1)
-        self.gate2(q_dev, wires=1)
-        self.gate3(q_dev, wires=1)
-        tqf.x(q_dev, wires=2, static=self.static_mode, parent_graph=self.graph)
-
-
-class CXLayer(tq.QuantumModule):
-    def __init__(self, n_wires):
-        super().__init__()
-        self.n_wires = n_wires
-
-    @tq.static_support
-    def forward(self, q_dev):
-        self.q_device = q_dev
-        tqf.cnot(q_dev, wires=[0, 1], static=self.static_mode, parent_graph=self.graph)
-
-
-class CXCXCXLayer(tq.QuantumModule):
-    def __init__(self, n_wires):
-        super().__init__()
-        self.n_wires = n_wires
-
-    @tq.static_support
-    def forward(self, q_dev):
-        self.q_device = q_dev
-        tqf.cnot(q_dev, wires=[0, 1], static=self.static_mode, parent_graph=self.graph)
-        tqf.cnot(q_dev, wires=[1, 2], static=self.static_mode, parent_graph=self.graph)
-        tqf.cnot(q_dev, wires=[2, 0], static=self.static_mode, parent_graph=self.graph)
-
-
-class SWAPSWAPLayer(tq.QuantumModule):
-    def __init__(self, n_wires):
-        super().__init__()
-        self.n_wires = n_wires
-
-    @tq.static_support
-    def forward(self, q_dev):
-        self.q_device = q_dev
-        tqf.swap(q_dev, wires=[0, 1], static=self.static_mode, parent_graph=self.graph)
-        tqf.swap(q_dev, wires=[1, 2], static=self.static_mode, parent_graph=self.graph)
-
-
-class Op1QAllLayer(tq.QuantumModule):
-    def __init__(self, op, n_wires: int, has_params=False, trainable=False):
-        super().__init__()
-        self.n_wires = n_wires
-        self.op = op
-        self.ops_all = tq.QuantumModuleList()
-        for k in range(n_wires):
-            self.ops_all.append(op(has_params=has_params, trainable=trainable))
-
-    @tq.static_support
-    def forward(self, q_device):
-        for k in range(self.n_wires):
-            self.ops_all[k](q_device, wires=k)
-
-
-class Op2QAllLayer(tq.QuantumModule):
-    """pattern:
-    circular = False
-    jump = 1: [0, 1], [1, 2], [2, 3], [3, 4], [4, 5]
-    jump = 2: [0, 2], [1, 3], [2, 4], [3, 5]
-    jump = 3: [0, 3], [1, 4], [2, 5]
-    jump = 4: [0, 4], [1, 5]
-    jump = 5: [0, 5]
-
-    circular = True
-    jump = 1: [0, 1], [1, 2], [2, 3], [3, 4], [4, 5], [5, 0]
-    jump = 2: [0, 2], [1, 3], [2, 4], [3, 5], [4, 0], [5, 1]
-    jump = 3: [0, 3], [1, 4], [2, 5], [3, 0], [4, 1], [5, 2]
-    jump = 4: [0, 4], [1, 5], [2, 0], [3, 1], [4, 2], [5, 3]
-    jump = 5: [0, 5], [1, 0], [2, 1], [3, 2], [4, 3], [5, 4]
-    """
-
-    def __init__(
-        self,
-        op,
-        n_wires: int,
-        has_params=False,
-        trainable=False,
-        wire_reverse=False,
-        jump=1,
-        circular=False,
-    ):
-        super().__init__()
-        self.n_wires = n_wires
-        self.jump = jump
-        self.circular = circular
-        self.op = op
-        self.ops_all = tq.QuantumModuleList()
-
-        # reverse the wires, for example from [1, 2] to [2, 1]
-        self.wire_reverse = wire_reverse
-
-        if circular:
-            n_ops = n_wires
-        else:
-            n_ops = n_wires - jump
-        for k in range(n_ops):
-            self.ops_all.append(op(has_params=has_params, trainable=trainable))
-
-    @tq.static_support
-    def forward(self, q_device):
-        for k in range(len(self.ops_all)):
-            wires = [k, (k + self.jump) % self.n_wires]
-            if self.wire_reverse:
-                wires.reverse()
-            self.ops_all[k](q_device, wires=wires)
-
-
-class Op2QFit32Layer(tq.QuantumModule):
-    def __init__(
-        self,
-        op,
-        n_wires: int,
-        has_params=False,
-        trainable=False,
-        wire_reverse=False,
-        jump=1,
-        circular=False,
-    ):
-        super().__init__()
-        self.n_wires = n_wires
-        self.jump = jump
-        self.circular = circular
-        self.op = op
-        self.ops_all = tq.QuantumModuleList()
-
-        # reverse the wires, for example from [1, 2] to [2, 1]
-        self.wire_reverse = wire_reverse
-
-        # if circular:
-        #     n_ops = n_wires
-        # else:
-        #     n_ops = n_wires - jump
-        n_ops = 32
-        for k in range(n_ops):
-            self.ops_all.append(op(has_params=has_params, trainable=trainable))
-
-    @tq.static_support
-    def forward(self, q_device):
-        for k in range(len(self.ops_all)):
-            wires = [k % self.n_wires, (k + self.jump) % self.n_wires]
-            if self.wire_reverse:
-                wires.reverse()
-            self.ops_all[k](q_device, wires=wires)
-
-
-class Op2QButterflyLayer(tq.QuantumModule):
-    """pattern: [0, 5], [1, 4], [2, 3]"""
-
-    def __init__(
-        self, op, n_wires: int, has_params=False, trainable=False, wire_reverse=False
-    ):
-        super().__init__()
-        self.n_wires = n_wires
-        self.op = op
-        self.ops_all = tq.QuantumModuleList()
-
-        # reverse the wires, for example from [1, 2] to [2, 1]
-        self.wire_reverse = wire_reverse
-
-        for k in range(n_wires // 2):
-            self.ops_all.append(op(has_params=has_params, trainable=trainable))
-
-    def forward(self, q_device):
-        for k in range(len(self.ops_all)):
-            wires = [k, self.n_wires - 1 - k]
-            if self.wire_reverse:
-                wires.reverse()
-            self.ops_all[k](q_device, wires=wires)
-
-
-class Op2QDenseLayer(tq.QuantumModule):
-    """pattern:
-    [0, 1], [0, 2], [0, 3], [0, 4], [0, 5]
-    [1, 2], [1, 3], [1, 4], [1, 5]
-    [2, 3], [2, 4], [2, 5]
-    [3, 4], [3, 5]
-    [4, 5]
-    """
-
-    def __init__(
-        self, op, n_wires: int, has_params=False, trainable=False, wire_reverse=False
-    ):
-        super().__init__()
-        self.n_wires = n_wires
-        self.op = op
-        self.ops_all = tq.QuantumModuleList()
-
-        # reverse the wires, for example from [1, 2] to [2, 1]
-        self.wire_reverse = wire_reverse
-
-        for k in range(self.n_wires * (self.n_wires - 1) // 2):
-            self.ops_all.append(op(has_params=has_params, trainable=trainable))
-
-    def forward(self, q_device):
-        k = 0
-        for i in range(self.n_wires - 1):
-            for j in range(i + 1, self.n_wires):
-                wires = [i, j]
-                if self.wire_reverse:
-                    wires.reverse()
-                self.ops_all[k](q_device, wires=wires)
-                k += 1
-
-
-class LayerTemplate0(tq.QuantumModule):
-    def __init__(self, arch: dict = None):
-        super().__init__()
-        self.n_wires = arch["n_wires"]
-        self.arch = arch
-
-        self.n_blocks = arch.get("n_blocks", None)
-        self.n_layers_per_block = arch.get("n_layers_per_block", None)
-
-        self.layers_all = self.build_layers()
-
-    def build_layers(self):
-        raise NotImplementedError
-
-    @tq.static_support
-    def forward(self, q_device: tq.QuantumDevice):
-        self.q_device = q_device
-        for k in range(len(self.layers_all)):
-            self.layers_all[k](q_device)
-
-
-class U3CU3Layer0(LayerTemplate0):
-    """u3 cu3 blocks"""
-
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.U3, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.CU3,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-        return layers_all
-
-
-class CU3Layer0(LayerTemplate0):
-    """u3 cu3 blocks"""
-
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.CU3,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=False,
-                )
-            )
-        return layers_all
-
-
-class CXRZSXLayer0(LayerTemplate0):
-    """CXRZSX blocks"""
-
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-
-        layers_all.append(
-            Op1QAllLayer(
-                op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
-            )
-        )
-        layers_all.append(
-            Op2QAllLayer(op=tq.CNOT, n_wires=self.n_wires, jump=1, circular=False)
-        )
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.SX, n_wires=self.n_wires, has_params=False, trainable=False
-                )
-            )
-        layers_all.append(
-            Op1QAllLayer(
-                op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
-            )
-        )
-        return layers_all
-
-
-class SethLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.RZZ,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-        return layers_all
-
-
-class SethLayer1(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.RZZ,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.RZZ,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-        return layers_all
-
-
-class SethLayer2(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op2QFit32Layer(
-                    op=tq.RZZ,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-        return layers_all
-
-
-class RZZLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.RZZ,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-        return layers_all
-
-
-class BarrenLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        layers_all.append(
-            Op1QAllLayer(
-                op=tq.SHadamard,
-                n_wires=self.n_wires,
-            )
-        )
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RX, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(Op2QAllLayer(op=tq.CZ, n_wires=self.n_wires, jump=1))
-        return layers_all
-
-
-class FarhiLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.RZX,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.RXX,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-        return layers_all
-
-
-class MaxwellLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RX, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(Op1QAllLayer(op=tq.S, n_wires=self.n_wires))
-            layers_all.append(
-                Op2QAllLayer(op=tq.CNOT, n_wires=self.n_wires, jump=1, circular=True)
-            )
-
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(Op1QAllLayer(op=tq.T, n_wires=self.n_wires))
-            layers_all.append(
-                Op2QAllLayer(op=tq.SWAP, n_wires=self.n_wires, jump=1, circular=True)
-            )
-
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(Op1QAllLayer(op=tq.Hadamard, n_wires=self.n_wires))
-            layers_all.append(
-                Op2QAllLayer(op=tq.SSWAP, n_wires=self.n_wires, jump=1, circular=True)
-            )
-
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.U1, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op2QAllLayer(
-                    op=tq.CU3,
-                    n_wires=self.n_wires,
-                    has_params=True,
-                    trainable=True,
-                    jump=1,
-                    circular=True,
-                )
-            )
-
-        return layers_all
-
-
-class RYRYCXLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(CXLayer(n_wires=self.n_wires))
-        return layers_all
-
-
-class RYRYRYCXCXCXLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(CXCXCXLayer(n_wires=self.n_wires))
-        return layers_all
-
-
-class RYRYRYLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-        return layers_all
-
-
-class RYRYRYSWAPSWAPLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(SWAPSWAPLayer(n_wires=self.n_wires))
-        return layers_all
-
-
-class SWAPSWAPLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(SWAPSWAPLayer(n_wires=self.n_wires))
-        return layers_all
-
-
-class RXYZCXLayer0(LayerTemplate0):
-    def build_layers(self):
-        layers_all = tq.QuantumModuleList()
-        for k in range(self.arch["n_blocks"]):
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RX, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RY, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op1QAllLayer(
-                    op=tq.RZ, n_wires=self.n_wires, has_params=True, trainable=True
-                )
-            )
-            layers_all.append(
-                Op2QAllLayer(op=tq.CNOT, n_wires=self.n_wires, jump=1, circular=True)
-            )
-        return layers_all
-
-
-layer_name_dict = {
-    "u3cu3_0": U3CU3Layer0,
-    "cu3_0": CU3Layer0,
-    "cxrzsx_0": CXRZSXLayer0,
-    "seth_0": SethLayer0,
-    "seth_1": SethLayer1,
-    "seth_2": SethLayer2,
-    "rzz_0": RZZLayer0,
-    "barren_0": BarrenLayer0,
-    "farhi_0": FarhiLayer0,
-    "maxwell_0": MaxwellLayer0,
-    "ryrycx": RYRYCXLayer0,
-    "ryryrycxcxcx": RYRYRYCXCXCXLayer0,
-    "ryryry": RYRYRYLayer0,
-    "swapswap": SWAPSWAPLayer0,
-    "ryryryswapswap": RYRYRYSWAPSWAPLayer0,
-    "rxyzcx_0": RXYZCXLayer0,
-}
diff --git a/torchquantum/macro.py b/torchquantum/macro.py
index 076f0748..f74a3676 100644
--- a/torchquantum/macro.py
+++ b/torchquantum/macro.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import math
 import torch
 import numpy as np
diff --git a/torchquantum/measurement/__init__.py b/torchquantum/measurement/__init__.py
new file mode 100644
index 00000000..bec5efe0
--- /dev/null
+++ b/torchquantum/measurement/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .measurements import *
diff --git a/torchquantum/measurement.py b/torchquantum/measurement/measurements.py
similarity index 99%
rename from torchquantum/measurement.py
rename to torchquantum/measurement/measurements.py
index 3a3722f5..ec0221a0 100644
--- a/torchquantum/measurement.py
+++ b/torchquantum/measurement/measurements.py
@@ -10,7 +10,7 @@
 from collections import Counter, OrderedDict
 
 from torchquantum.functional import mat_dict
-from torchquantum.operators import op_name_dict
+from torchquantum.operator import op_name_dict, Observable
 from copy import deepcopy
 import matplotlib.pyplot as plt
 
@@ -277,7 +277,7 @@ def expval_joint_analytical(
 def expval(
     qdev: tq.QuantumDevice,
     wires: Union[int, List[int]],
-    observables: Union[tq.Observable, List[tq.Observable]],
+    observables: Union[Observable, List[Observable]],
 ):
 
     all_dims = np.arange(qdev.states.dim())
diff --git a/torchquantum/module.py b/torchquantum/module.py
deleted file mode 100644
index 4a97dd32..00000000
--- a/torchquantum/module.py
+++ /dev/null
@@ -1,188 +0,0 @@
-import torch.nn as nn
-import torchquantum as tq
-
-from abc import ABCMeta
-from typing import Iterable
-
-__all__ = [
-    "QuantumModule",
-    "QuantumModuleList",
-    "QuantumModuleDict",
-]
-
-
-class QuantumModule(nn.Module):
-    def __init__(self) -> None:
-        super().__init__()
-        self.static_mode = False
-        self.graph = None
-        self.parent_graph = None
-        self.is_graph_top = False
-        self.unitary = None
-        self.wires = None
-        self.n_wires = None
-        self.q_device = None
-        # this is for gpu or cpu, not q device
-        self.device = None
-        # for the static tensor network simulation optimizations
-        self.wires_per_block = None
-        self.qiskit_processor = None
-        self.noise_model_tq = None
-        self.Operator_list = None
-    
-    def load_op_history(self, op_history):
-        """load operation history
-            {
-                "name": name,  # type: ignore
-                "wires": np.array(wires).squeeze().tolist(),
-                "params": params.squeeze().detach().cpu().numpy().tolist() if params is not None else None,
-                "inverse": inverse,
-                "trainable": params.requires_grad if params is not None else False,
-            }
-
-        """
-        Operator_list = []
-        for op in op_history:
-            Oper = tq.op_name_dict[op["name"]]
-            trainable = op.get("trainable", False)
-            has_params = True if ((op.get("params", None) is not None) or trainable) else False
-            init_params = op.get("params", None)
-            n_wires = len(op["wires"]) if isinstance(op["wires"], Iterable) else 1
-            wires = op['wires']
-            inverse = op.get("inverse", False)
-            Operator_list.append(Oper(
-                has_params=has_params,
-                trainable=trainable,
-                init_params=init_params,
-                n_wires=n_wires,
-                wires=wires,
-                inverse=inverse,
-            ))
-
-        self.Operator_list = tq.QuantumModuleList(Operator_list)
-    
-
-    @classmethod
-    def from_op_history(cls, op_history):
-        """Create a QuantumModule from op_history
-        Args:
-            op_history (list): A list of op in function dict format
-        """
-        qmodule = cls()
-        qmodule.load_op_history(op_history)
-        qmodule.forward = qmodule.forward_Operators_list
-        return qmodule
-
-    def forward_Operators_list(self, qdev):
-        assert self.Operator_list is not None, "Operator_list should not contain nothing"
-        for Oper in self.Operator_list:
-            Oper(qdev)
-
-    def set_noise_model_tq(self, noise_model_tq):
-        for module in self.modules():
-            module.noise_model_tq = noise_model_tq
-
-    def set_qiskit_processor(self, processor):
-        for module in self.modules():
-            module.qiskit_processor = processor
-
-    def set_wires_per_block(self, wires_per_block):
-        self.wires_per_block = wires_per_block
-
-    def static_on(self, is_graph_top=True, wires_per_block=3):
-        self.wires_per_block = wires_per_block
-        # register graph of itself and parent
-        self.static_mode = True
-        self.is_graph_top = is_graph_top
-        if self.graph is None:
-            self.graph = tq.QuantumGraph()
-
-        for module in self.children():
-            if isinstance(module, nn.ModuleList) or isinstance(module, nn.ModuleDict):
-                # if QuantumModuleList or QuantumModuleDict, its graph will
-                # be the same as the parent graph because ModuleList and
-                # ModuleDict do not call the forward function
-                module.graph = self.graph
-            module.parent_graph = self.graph
-            if not isinstance(module, tq.QuantumDevice):
-                module.static_on(is_graph_top=False)
-
-    def static_off(self):
-        self.static_mode = False
-        self.graph = None
-        for module in self.children():
-            if not isinstance(module, tq.QuantumDevice):
-                module.static_off()
-
-    def set_graph_build_finish(self):
-        self.graph.is_list_finish = True
-        for module in self.graph.module_list:
-            if not isinstance(module, tq.QuantumDevice):
-                module.set_graph_build_finish()
-
-    def static_forward(self, q_device: tq.QuantumDevice):
-        self.q_device = q_device
-        self.device = q_device.states.device
-        self.graph.q_device = q_device
-        self.graph.device = q_device.states.device
-        # self.unitary, self.wires, self.n_wires = \
-        self.graph.forward(wires_per_block=self.wires_per_block)
-        # tqf.qubitunitary(
-        #     q_device=self.q_device,
-        #     wires=self.wires,
-        #     params=self.unitary
-        # )
-
-    # def __repr__(self):
-    #     if self.Operator_list is not None:
-    #         return f"QuantumModule with Operator_list {self.Operator_list}"
-    #     else:
-    #         return "QuantumModule"
-
-    def get_unitary(self, q_device: tq.QuantumDevice, x=None):
-        original_wires_per_block = self.wires_per_block
-        original_static_mode = self.static_mode
-        self.static_off()
-        self.static_on(wires_per_block=q_device.n_wires)
-        self.q_device = q_device
-        self.device = q_device.state.device
-        self.graph.q_device = q_device
-        self.graph.device = q_device.state.device
-
-        self.is_graph_top = False
-        # forward to register all modules to the module list, but do not
-        # apply the unitary to the state vector
-        if x is None:
-            self.forward(q_device)
-        else:
-            self.forward(q_device, x)
-        self.is_graph_top = True
-
-        self.graph.build(wires_per_block=q_device.n_wires)
-        self.graph.build_static_matrix()
-        unitary = self.graph.get_unitary()
-
-        self.static_off()
-        if original_static_mode:
-            self.static_on(original_wires_per_block)
-
-        return unitary
-
-
-class QuantumModuleList(nn.ModuleList, QuantumModule, metaclass=ABCMeta):
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-
-class QuantumModuleDict(nn.ModuleDict, QuantumModule, metaclass=ABCMeta):
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-
-
-def test():
-    pass
-
-
-if __name__ == "__main__":
-    test()
diff --git a/torchquantum/module/__init__.py b/torchquantum/module/__init__.py
new file mode 100644
index 00000000..717817e5
--- /dev/null
+++ b/torchquantum/module/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .modules import *
diff --git a/torchquantum/module/modules.py b/torchquantum/module/modules.py
new file mode 100644
index 00000000..34f2ec11
--- /dev/null
+++ b/torchquantum/module/modules.py
@@ -0,0 +1,397 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch.nn as nn
+import torchquantum as tq
+
+from abc import ABCMeta
+from typing import Iterable
+
+__all__ = [
+    "QuantumModule",
+    "QuantumModuleList",
+    "QuantumModuleDict",
+]
+
+
+class QuantumModule(nn.Module):
+    """Module for quantum computations.
+    
+    Attributes:
+        static_mode (bool): Indicates whether the module is in static mode.
+        graph (tq.QuantumGraph): The quantum graph representation.
+        parent_graph (tq.QuantumGraph): The parent quantum graph.
+        is_graph_top (bool): Indicates whether the module is the top level of the graph.
+        unitary (torch.Tensor): The unitary matrix.
+        wires (List[int]): The wires.
+        n_wires (int): The number of wires.
+        q_device (tq.QuantumDevice): The quantum device.
+        device (torch.device): The device (CPU or GPU).
+        wires_per_block (int): The number of wires per block for static tensor network simulation.
+        qiskit_processor: The Qiskit processor.
+        noise_model_tq: The noise model.
+        Operator_list (tq.QuantumModuleList): The list of quantum operators.
+    
+    Methods:
+        __init__(self):
+            Initialize the QuantumModule.
+        load_op_history(self, op_history):
+            Load the operation history.
+        from_op_history(cls, op_history):
+            Create a QuantumModule from the operation history.
+    """
+    
+    def __init__(self) -> None:
+        """Initialize the QuantumModule.
+        
+        Returns:
+            None.
+            
+        Examples:
+            >>> qmodule = QuantumModule()
+        """
+        
+        super().__init__()
+        self.static_mode = False
+        self.graph = None
+        self.parent_graph = None
+        self.is_graph_top = False
+        self.unitary = None
+        self.wires = None
+        self.n_wires = None
+        self.q_device = None
+        # this is for gpu or cpu, not q device
+        self.device = None
+        # for the static tensor network simulation optimizations
+        self.wires_per_block = None
+        self.qiskit_processor = None
+        self.noise_model_tq = None
+        self.Operator_list = None
+    
+    def load_op_history(self, op_history):
+        """Load the operation history.
+        
+        Args:
+            op_history (list of dict): A list of operations in function dict format.
+
+        Returns:
+            None.
+            
+        Examples:
+            >>> op_history = [
+            ...     {
+            ...         "name": name,   # type: ignore
+            ...         "wires": np.array(wires).squeeze().tolist(),
+            ...         "params": params.squeeze().detach().cpu().numpy().tolist() if params is not None else None,
+            ...         "inverse": inverse,
+            ...         "trainable": params.requires_grad if params is not None else False,
+            ...     }
+            ... ]
+            >>> qmodule.load_op_history(op_history)
+        """
+
+        Operator_list = []
+        for op in op_history:
+            Oper = tq.op_name_dict[op["name"]]
+            trainable = op.get("trainable", False)
+            has_params = True if ((op.get("params", None) is not None) or trainable) else False
+            init_params = op.get("params", None)
+            n_wires = len(op["wires"]) if isinstance(op["wires"], Iterable) else 1
+            wires = op['wires']
+            inverse = op.get("inverse", False)
+            Operator_list.append(Oper(
+                has_params=has_params,
+                trainable=trainable,
+                init_params=init_params,
+                n_wires=n_wires,
+                wires=wires,
+                inverse=inverse,
+            ))
+
+        self.Operator_list = tq.QuantumModuleList(Operator_list)
+    
+
+    @classmethod
+    def from_op_history(cls, op_history):
+        """Create a QuantumModule from the operation history.
+
+        Args:
+            op_history (list): A list of operations in function dict format.
+
+        Returns:
+            QuantumModule: The created QuantumModule.
+        
+        Examples:
+            >>> op_history = [
+            ...     {
+            ...         "name": name,   # type: ignore
+            ...         "wires": np.array(wires).squeeze().tolist(),
+            ...         "params": params.squeeze().detach().cpu().numpy().tolist() if params is not None else None,
+            ...         "inverse": inverse,
+            ...         "trainable": params.requires_grad if params is not None else False,
+            ...     }
+            ... ]
+            >>> qmodule = QuantumModule.from_op_history(op_history)
+        """
+        
+        qmodule = cls()
+        qmodule.load_op_history(op_history)
+        qmodule.forward = qmodule.forward_Operators_list
+        return qmodule
+
+    def forward_Operators_list(self, qdev):
+        """Forward the list of quantum operators.
+
+        Args:
+            qdev (tq.QuantumDevice): The quantum device.
+        
+        Returns:
+            None.
+
+        Examples:
+            >>> qdev = tq.QuantumDevice(n_wires=2)
+            >>> qmodule.forward_Operators_list(qdev)
+        """
+        
+        assert self.Operator_list is not None, "Operator_list should not contain nothing"
+        for Oper in self.Operator_list:
+            Oper(qdev)
+
+    def set_noise_model_tq(self, noise_model_tq):
+        """Set the noise model for the QuantumModule and its sub-modules.
+
+        Args:
+            noise_model_tq: The noise model.
+        
+        Returns:
+            None.
+            
+        Examples:
+            >>> noise_model_tq = ...
+            >>> qmodule.set_noise_model_tq(noise_model_tq)
+        """
+        
+        for module in self.modules():
+            module.noise_model_tq = noise_model_tq
+
+    def set_qiskit_processor(self, processor):
+        """Set the Qiskit processor for the QuantumModule and its sub-modules.
+
+        Args:
+            processor: The Qiskit processor.
+
+        Returns:
+            None.
+
+        Examples:
+            >>> processor = ...
+            >>> qmodule.set_qiskit_processor(processor)
+        """
+        
+        for module in self.modules():
+            module.qiskit_processor = processor
+
+    def set_wires_per_block(self, wires_per_block):
+        """Set the number of wires per block for static tensor network simulation.
+
+        Args:
+            wires_per_block (int): The number of wires per block.
+
+        Returns:
+            None.
+
+        Examples:
+            >>> qmodule.set_wires_per_block(3)
+        """
+        
+        self.wires_per_block = wires_per_block
+
+    def static_on(self, is_graph_top=True, wires_per_block=3):
+        """Enable static mode for the QuantumModule.
+
+        Args:
+            is_graph_top (bool): Indicates whether the module is the top level of the graph.
+                Defaults to True.
+            wires_per_block (int): The number of wires per block.
+                Defaults to 3.
+
+        Returns:
+            None.
+
+        Examples:
+            >>> qmodule.static_on(wires_per_block=5)
+        """
+        
+        self.wires_per_block = wires_per_block
+        # register graph of itself and parent
+        self.static_mode = True
+        self.is_graph_top = is_graph_top
+        if self.graph is None:
+            self.graph = tq.QuantumGraph()
+
+        for module in self.children():
+            if isinstance(module, nn.ModuleList) or isinstance(module, nn.ModuleDict):
+                # if QuantumModuleList or QuantumModuleDict, its graph will
+                # be the same as the parent graph because ModuleList and
+                # ModuleDict do not call the forward function
+                module.graph = self.graph
+            module.parent_graph = self.graph
+            if not isinstance(module, tq.QuantumDevice):
+                module.static_on(is_graph_top=False)
+
+    def static_off(self):
+        """Disable static mode for the QuantumModule.
+
+        Returns:
+            None.
+
+        Examples:
+            >>> qmodule.static_off()
+        """
+        
+        self.static_mode = False
+        self.graph = None
+        for module in self.children():
+            if not isinstance(module, tq.QuantumDevice):
+                module.static_off()
+
+    def set_graph_build_finish(self):
+        """Set the graph build finish flag for the QuantumModule and its sub-modules.
+        
+        Returns:
+            None.        
+
+        Examples:
+            >>> qmodule.set_graph_build_finish()
+        """
+        
+        self.graph.is_list_finish = True
+        for module in self.graph.module_list:
+            if not isinstance(module, tq.QuantumDevice):
+                module.set_graph_build_finish()
+
+    def static_forward(self, q_device: tq.QuantumDevice):
+        """Static forward pass of the QuantumModule with the given quantum device.
+
+        Args:
+            q_device (tq.QuantumDevice): The quantum device.
+        
+        Returns:
+            None.
+            
+        Example:
+            >>> q_device = tq.QuantumDevice(n_wires=2)
+            >>> qmodule.static_forward(q_device)
+        """
+        
+        self.q_device = q_device
+        self.device = q_device.states.device
+        self.graph.q_device = q_device
+        self.graph.device = q_device.states.device
+        # self.unitary, self.wires, self.n_wires = \
+        self.graph.forward(wires_per_block=self.wires_per_block)
+        # tqf.qubitunitary(
+        #     q_device=self.q_device,
+        #     wires=self.wires,
+        #     params=self.unitary
+        # )
+
+    # def __repr__(self):
+    #     if self.Operator_list is not None:
+    #         return f"QuantumModule with Operator_list {self.Operator_list}"
+    #     else:
+    #         return "QuantumModule"
+
+    def get_unitary(self, q_device: tq.QuantumDevice, x=None):
+        """Compute the unitary matrix for the QuantumModule with the given quantum device and input.
+
+        Args:
+            q_device (tq.QuantumDevice): The quantum device.
+            x (Optional): The input.
+                Defaults to None.
+
+        Returns:
+            torch.Tensor: The unitary matrix.
+
+        Example:
+            >>> q_device = tq.QuantumDevice(n_wires=2)
+            >>> unitary = qmodule.get_unitary(q_device)
+        """
+        
+        original_wires_per_block = self.wires_per_block
+        original_static_mode = self.static_mode
+        self.static_off()
+        self.static_on(wires_per_block=q_device.n_wires)
+        self.q_device = q_device
+        self.device = q_device.state.device
+        self.graph.q_device = q_device
+        self.graph.device = q_device.state.device
+
+        self.is_graph_top = False
+        # forward to register all modules to the module list, but do not
+        # apply the unitary to the state vector
+        if x is None:
+            self.forward(q_device)
+        else:
+            self.forward(q_device, x)
+        self.is_graph_top = True
+
+        self.graph.build(wires_per_block=q_device.n_wires)
+        self.graph.build_static_matrix()
+        unitary = self.graph.get_unitary()
+
+        self.static_off()
+        if original_static_mode:
+            self.static_on(original_wires_per_block)
+
+        return unitary
+
+
+class QuantumModuleList(nn.ModuleList, QuantumModule, metaclass=ABCMeta):
+    """A list-based container for QuantumModules."""
+    
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+
+class QuantumModuleDict(nn.ModuleDict, QuantumModule, metaclass=ABCMeta):
+    """A dictionary-based container for QuantumModules."""
+    
+    def __init__(self, *args, **kwargs):
+        super().__init__(*args, **kwargs)
+
+
+
+def test():
+    """Test function.
+    
+    Returns:
+        None.
+    """
+    
+    pass
+
+
+if __name__ == "__main__":
+    test()
diff --git a/torchquantum/node/__init__.py b/torchquantum/node/__init__.py
new file mode 100644
index 00000000..21cae8ca
--- /dev/null
+++ b/torchquantum/node/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .nodes import *
diff --git a/torchquantum/node.py b/torchquantum/node/nodes.py
similarity index 64%
rename from torchquantum/node.py
rename to torchquantum/node/nodes.py
index 1581865a..f5d10220 100644
--- a/torchquantum/node.py
+++ b/torchquantum/node/nodes.py
@@ -1,8 +1,32 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torchquantum as tq
 
 from torchquantum.encoding import encoder_op_list_name_dict
-from torchquantum.layers import layer_name_dict
+from torchquantum.layer import layer_name_dict
 import numpy as np
 import datetime
 
@@ -14,11 +38,53 @@
 
 
 class QuantumNode(tq.QuantumModule):
-    """
-    a quantum node contains a q device, encoder, q layer and measure
+    """A quantum node contains a q device, encoder, q layer and measure
+    
+    Attributes:
+        arch (dict): The architecture configuration for the node.
+        q_device (tq.QuantumDevice): The quantum device.
+        encoder (tq.GeneralEncoder): The encoder.
+        q_layer (tq.QuantumLayer): The quantum layer.
+        measure (tq.MeasureAll): The measurement operator.
+        act_norm (str): The activation normalization method.
+        x_before_add_noise (torch.Tensor): The input tensor before adding noise.
+        x_before_add_noise_second (torch.Tensor): The input tensor before adding noise (second step).
+        x_before_act_quant (torch.Tensor): The input tensor before activation quantization.
+        x_before_norm (torch.Tensor): The input tensor before normalization.
+        circuit_in (torch.Tensor): The input tensor of the circuit.
+        circuit_out (torch.Tensor): The output tensor of the circuit.
+        shift_this_step (List[bool]): The list indicating whether to shift parameters in each step.
+        cool_down (List[int]): The cooling down values.
+        triger_cd (List[int]): The trigger cooling down values.
+        bn (torch.nn.BatchNorm1d): The batch normalization layer.
+        node_id (int): The ID of the node.
+        pre_specified_mean_std (dict): The pre-specified mean and standard deviation.
+        grad_qlayer (List[Optional[torch.Tensor]]): The gradients of the quantum layer.
+        grad_encoder (List[Optional[torch.Tensor]]): The gradients of the encoder.
+    
+    Methods:
+        __init__(self, arch, act_norm, node_id): Initialize the QuantumNode.
+        forward(self, x, use_qiskit=False, is_last_node=False, parallel=True): Forward pass of the QuantumNode.
+        run_circuit(self, inputs): Run the circuit without applying normalization or noise.
+        shift_and_run(self, x, use_qiskit=False, is_last_node=False, is_first_node=False, parallel=True):
+            Shift the parameters and run the circuit.
     """
 
     def __init__(self, arch, act_norm, node_id):
+        """Initialize the QuantumNode.
+
+        Args:
+            arch (dict): The architecture configuration for the node.
+            act_norm (str): The activation normalization method.
+            node_id (int): The ID of the node.
+
+        Example:
+            >>> arch = {"n_wires": 2, "encoder_op_list_name": "default", "q_layer_name": "default"}
+            >>> act_norm = "batch_norm"
+            >>> node_id = 0
+            >>> node = QuantumNode(arch, act_norm, node_id)
+        """
+        
         super().__init__()
         self.arch = arch
         self.q_device = tq.QuantumDevice(n_wires=arch["n_wires"])
@@ -50,6 +116,26 @@ def __init__(self, arch, act_norm, node_id):
         self.grad_encoder = None
 
     def forward(self, x, use_qiskit=False, is_last_node=False, parallel=True):
+        """Forward pass of the QuantumNode.
+
+        Args:
+            x (torch.Tensor): The input tensor.
+                Defaults to False.
+            use_qiskit (bool): Whether to use the Qiskit processor.
+                Defaults to False.
+            is_last_node (bool): Whether the node is the last node in the model.
+                Defaults to False.
+            parallel (bool): Whether to run the circuit in parallel.
+                Defaults to True.
+
+        Returns:
+            torch.Tensor: The output tensor.
+
+        Example:
+            >>> x = torch.randn(10, 2)
+            >>> node.forward(x, use_qiskit=True, is_last_node=False, parallel=True)
+        """
+        
         if use_qiskit:
             x = self.qiskit_processor.process_parameterized(
                 self.q_device,
@@ -121,6 +207,19 @@ def forward(self, x, use_qiskit=False, is_last_node=False, parallel=True):
         return x
 
     def run_circuit(self, inputs):
+        """Run the circuit without applying normalization or noise.
+
+        Args:
+            inputs (torch.Tensor): The input tensor.
+
+        Returns:
+            torch.Tensor: The output tensor.
+
+        Example:
+            >>> inputs = torch.randn(10, 2)
+            >>> node.run_circuit(inputs)
+        """
+        
         self.encoder(self.q_device, inputs)
         self.q_layer(self.q_device)
         x = self.measure(self.q_device)
@@ -134,6 +233,28 @@ def shift_and_run(
         is_first_node=False,
         parallel=True,
     ):
+        """Shift the parameters and run the circuit.
+
+        Args:
+            x (torch.Tensor): The input tensor.
+            use_qiskit (bool): Whether to use the Qiskit processor.
+                Defaults to False.
+            is_last_node (bool): Whether the node is the last node in the model.
+                Defaults to False.
+            is_first_node (bool): Whether the node is the first node in the model.
+                Defaults to False.
+            parallel (bool): Whether to run the circuit in parallel.
+                Defaults to True.
+
+        Returns:
+            torch.Tensor: The output tensor.
+            datetime.timedelta: The time spent during the circuit execution.
+
+        Example:
+            >>> x = torch.randn(10, 2)
+            >>> node.shift_and_run(x, use_qiskit=True, is_last_node=False, is_first_node=False, parallel=True)
+        """
+        
         import numpy as np
 
         self.circuit_in = x
@@ -293,7 +414,23 @@ def shift_and_run(
         return x, time_spent
 
 
-def build_nodes(node_archs, act_norm=None):
+def build_nodes(node_archs, act_norm=None) -> torchquantum.QuantumModuleList:
+    """Build a list of QuantumNode instances based on the given architectures.
+
+    Args:
+        node_archs (list): The list of node architectures.
+        act_norm (str): The activation normalization method.
+            Defaults to None.
+
+    Returns:
+        torchquantum.QuantumModuleList: The list of QuantumNode instances.
+        
+    Example:
+        >>> node_archs = [...]
+        >>> act_norm = "batch_norm"
+        >>> nodes = build_nodes(node_archs, act_norm)
+    """
+    
     nodes = tq.QuantumModuleList()
     for k, node_arch in enumerate(node_archs):
         nodes.append(QuantumNode(node_arch, act_norm=act_norm, node_id=k))
diff --git a/torchquantum/noise_model/__init__.py b/torchquantum/noise_model/__init__.py
new file mode 100644
index 00000000..dc85cd77
--- /dev/null
+++ b/torchquantum/noise_model/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .noise_models import *
diff --git a/torchquantum/noise_model.py b/torchquantum/noise_model/noise_models.py
similarity index 69%
rename from torchquantum/noise_model.py
rename to torchquantum/noise_model/noise_models.py
index 98166abf..571314e9 100644
--- a/torchquantum/noise_model.py
+++ b/torchquantum/noise_model/noise_models.py
@@ -1,10 +1,34 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import numpy as np
 import torch
 import torchquantum as tq
 
 from torchpack.utils.logging import logger
 from qiskit.providers.aer.noise import NoiseModel
-from torchquantum.utils import get_provider
+from torchquantum.util import get_provider
 
 
 __all__ = [
@@ -25,6 +49,33 @@ def cos_adjust_noise(
     prob_schedule_separator,
     orig_noise_total_prob,
 ):
+    """
+        Adjust the noise probability based on the current epoch and a cosine schedule.
+
+        Args:
+            current_epoch (int): The current epoch.
+            n_epochs (int): The total number of epochs.
+            prob_schedule (str): The probability schedule type. Possible values are:
+                - None: No schedule, use the original noise probability.
+                - "increase": Increase the noise probability using a cosine schedule.
+                - "decrease": Decrease the noise probability using a cosine schedule.
+                - "increase_decrease": Increase the noise probability until a separator epoch,
+                  then decrease it using cosine schedules.
+            prob_schedule_separator (int): The epoch at which the schedule changes for
+                "increase_decrease" mode.
+            orig_noise_total_prob (float): The original noise probability.
+
+        Returns:
+            float: The adjusted noise probability based on the schedule.
+
+        Note:
+            The adjusted noise probability is returned as a float between 0 and 1.
+
+        Raises:
+            None.
+
+        """
+
     if prob_schedule is None:
         noise_total_prob = orig_noise_total_prob
     elif prob_schedule == "increase":
@@ -82,6 +133,32 @@ def cos_adjust_noise(
 
 
 def apply_readout_error_func(x, c2p_mapping, measure_info):
+    """
+        Apply readout error to the measurement outcomes.
+
+        Args:
+            x (torch.Tensor): The measurement outcomes, represented as a tensor of shape (batch_size, num_qubits).
+            c2p_mapping (dict): Mapping from qubit indices to physical wire indices.
+            measure_info (dict): Measurement information dictionary containing the probabilities for different outcomes.
+
+        Returns:
+            torch.Tensor: The measurement outcomes after applying the readout error, represented as a tensor of the same shape as x.
+
+        Note:
+            The readout error is applied based on the given mapping and measurement information.
+            The measurement information dictionary should have the following structure:
+            {
+                (wire_1,): {"probabilities": [[p_0, p_1], [p_0, p_1]]},
+                (wire_2,): {"probabilities": [[p_0, p_1], [p_0, p_1]]},
+                ...
+            }
+            where wire_1, wire_2, ... are the physical wire indices, and p_0 and p_1 are the probabilities of measuring 0 and 1, respectively,
+            for each wire.
+
+        Raises:
+            None.
+
+        """
     # add readout error
     noise_free_0_probs = (x + 1) / 2
     noise_free_1_probs = 1 - (x + 1) / 2
@@ -118,8 +195,22 @@ def apply_readout_error_func(x, c2p_mapping, measure_info):
 
 
 class NoiseCounter:
-    '''count all the pauli error gate being sampled in self.sample_noise_op()
-    '''
+    """
+        A class for counting the occurrences of Pauli error gates.
+
+        Attributes:
+            counter_x (int): Counter for Pauli X errors.
+            counter_y (int): Counter for Pauli Y errors.
+            counter_z (int): Counter for Pauli Z errors.
+            counter_X (int): Counter for Pauli X errors (for two-qubit gates).
+            counter_Y (int): Counter for Pauli Y errors (for two-qubit gates).
+            counter_Z (int): Counter for Pauli Z errors (for two-qubit gates).
+
+        Methods:
+            add(error): Adds a Pauli error to the counters based on the error type.
+            __str__(): Returns a string representation of the counters.
+
+        """
     def __init__(self):
         self.counter_x = 0
         self.counter_y = 0
@@ -152,8 +243,28 @@ def __str__(self) -> str:
 
 class NoiseModelTQ(object):
     """
-    apply gate insertion and readout
-    """
+        A class for applying gate insertion and readout errors.
+
+        Attributes:
+            noise_model_name (str): Name of the noise model.
+            n_epochs (int): Number of epochs.
+            noise_total_prob (float): Total probability of noise.
+            ignored_ops (tuple): Operations to be ignored.
+            prob_schedule (list): Probability schedule.
+            prob_schedule_separator (str): Separator for probability schedule.
+            factor (float): Factor for adjusting probabilities.
+            add_thermal (bool): Flag indicating whether to add thermal relaxation.
+
+        Methods:
+            adjust_noise(current_epoch): Adjusts the noise based on the current epoch.
+            clean_parsed_noise_model_dict(nm_dict, ignored_ops): Cleans the parsed noise model dictionary.
+            parse_noise_model_dict(nm_dict): Parses the noise model dictionary.
+            magnify_probs(probs): Magnifies the probabilities based on a factor.
+            sample_noise_op(op_in): Samples a noise operation based on the given operation.
+            apply_readout_error(x): Applies readout error to the input.
+
+        """
+
 
     def __init__(
         self,
@@ -363,8 +474,25 @@ def apply_readout_error(self, x):
 
 class NoiseModelTQActivation(object):
     """
-    add noise to the activations
-    """
+        A class for adding noise to the activations.
+
+        Attributes:
+            mean (tuple): Mean values of the noise.
+            std (tuple): Standard deviation values of the noise.
+            n_epochs (int): Number of epochs.
+            prob_schedule (list): Probability schedule.
+            prob_schedule_separator (str): Separator for probability schedule.
+            after_norm (bool): Flag indicating whether noise should be added after normalization.
+            factor (float): Factor for adjusting the noise.
+
+        Methods:
+            adjust_noise(current_epoch): Adjusts the noise based on the current epoch.
+            sample_noise_op(op_in): Samples a noise operation.
+            apply_readout_error(x): Applies readout error to the input.
+            add_noise(x, node_id, is_after_norm): Adds noise to the activations.
+
+        """
+
 
     def __init__(
         self,
@@ -432,8 +560,23 @@ def add_noise(self, x, node_id, is_after_norm=False):
 
 class NoiseModelTQPhase(object):
     """
-    add noise to rotation parameters
-    """
+        A class for adding noise to rotation parameters.
+
+        Attributes:
+            mean (float): Mean value of the noise.
+            std (float): Standard deviation value of the noise.
+            n_epochs (int): Number of epochs.
+            prob_schedule (list): Probability schedule.
+            prob_schedule_separator (str): Separator for probability schedule.
+            factor (float): Factor for adjusting the noise.
+
+        Methods:
+            adjust_noise(current_epoch): Adjusts the noise based on the current epoch.
+            sample_noise_op(op_in): Samples a noise operation.
+            apply_readout_error(x): Applies readout error to the input.
+            add_noise(phase): Adds noise to the rotation parameters.
+
+        """
 
     def __init__(
         self,
@@ -494,16 +637,41 @@ def add_noise(self, phase):
 
 
 class NoiseModelTQReadoutOnly(NoiseModelTQ):
+    """
+       A subclass of NoiseModelTQ that applies readout errors only.
+
+       This class inherits from NoiseModelTQ and overrides the sample_noise_op method to exclude the insertion of any noise operations other than readout errors. It is designed for scenarios where only readout errors are considered, and all other noise sources are ignored.
+
+       Methods:
+           sample_noise_op(op_in): Returns an empty list, indicating no noise operations are applied.
+       """
     def sample_noise_op(self, op_in):
         return []
 
 
 class NoiseModelTQQErrorOnly(NoiseModelTQ):
+    """
+        A subclass of NoiseModelTQ that applies only readout errors.
+
+        This class inherits from NoiseModelTQ and overrides the apply_readout_error method to apply readout errors. It removes activation noise and only focuses on readout errors in the noise model.
+
+        Methods:
+            apply_readout_error(x): Applies readout error to the given activation values.
+
+        """
     def apply_readout_error(self, x):
         return x
 
 
 class NoiseModelTQActivationReadout(NoiseModelTQActivation):
+    """
+       A subclass of NoiseModelTQActivation that applies readout errors.
+
+       This class inherits from NoiseModelTQActivation and overrides the apply_readout_error method to incorporate readout errors. It combines activation noise and readout errors into the noise model.
+
+       Methods:
+           apply_readout_error(x): Applies readout error to the given activation values
+       """
     def __init__(
         self,
         noise_model_name,
@@ -544,6 +712,14 @@ def apply_readout_error(self, x):
 
 
 class NoiseModelTQPhaseReadout(NoiseModelTQPhase):
+    """
+        A subclass of NoiseModelTQPhase that applies readout errors to phase values.
+
+        This class inherits from NoiseModelTQPhase and overrides the apply_readout_error method to apply readout errors specifically to phase values. It uses the noise model provided to introduce readout errors.
+
+        Methods:
+            apply_readout_error(x): Applies readout error to the given phase values.
+        """
     def __init__(
         self,
         noise_model_name,
diff --git a/torchquantum/operator/__init__.py b/torchquantum/operator/__init__.py
new file mode 100644
index 00000000..3d08a33e
--- /dev/null
+++ b/torchquantum/operator/__init__.py
@@ -0,0 +1,26 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .operators import *
+from .op_hamil_exp import *
diff --git a/torchquantum/operator/op_hamil_exp.py b/torchquantum/operator/op_hamil_exp.py
new file mode 100644
index 00000000..e9e16809
--- /dev/null
+++ b/torchquantum/operator/op_hamil_exp.py
@@ -0,0 +1,150 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+from torchquantum.module import QuantumModule
+from torchquantum.algorithm import Hamiltonian
+import torchquantum.functional as tqf
+
+from typing import List
+
+import numpy as np
+
+__all__ = [
+    'OpHamilExp',
+    'OpPauliExp',
+    ]
+
+
+class OpHamilExp(QuantumModule):
+    """Matrix exponential operation.
+    exp(-i * theta * H / 2)
+    the default theta is 0.0
+    """
+    def __init__(self,
+                 hamil: Hamiltonian,
+                 trainable: bool = True,
+                 theta: float = 0.0):
+        """Initialize the OpHamilExp module.
+        
+        Args:
+            hamil: The Hamiltonian.
+            has_params: Whether the module has parameters.
+            trainable: Whether the parameters are trainable.
+            theta: The initial value of theta.
+        
+        """
+        super().__init__()
+        if trainable:
+            self.theta = torch.nn.parameter.Parameter(torch.tensor(theta))
+        else:
+            self.theta = torch.tensor(theta)
+        self.hamil = hamil
+    
+    def get_exponent_matrix(self):
+        """Get the matrix on exponent."""
+        return self.hamil.matrix * -1j * self.theta / 2
+    
+    @property
+    def exponent_matrix(self):
+        """Get the matrix on exponent."""
+        return self.get_exponent_matrix()
+
+    def get_matrix(self):
+        """Get the overall matrix."""
+        return torch.matrix_exp(self.exponent_matrix)
+    
+    @property
+    def matrix(self):
+        """Get the overall matrix."""
+        return self.get_matrix()
+    
+    def forward(self, qdev, wires):
+        """Forward the OpHamilExp module.
+        Args:
+            qdev: The QuantumDevice.
+            wires: The wires.
+
+        """
+        matrix = self.matrix.to(qdev.device)
+        tqf.qubitunitaryfast(
+            q_device=qdev,
+            wires=wires,
+            params=matrix,
+        )
+
+
+class OpPauliExp(OpHamilExp):
+    def __init__(self,
+                 coeffs: List[float],
+                 paulis: List[str],
+                 endianness: str = "big",
+                 trainable: bool = True,
+                 theta: float = 0.0):
+        """Initialize the OpPauliExp module.
+        
+        Args:
+            coeffs: The coefficients of the Hamiltonian.
+            paulis: The operators of the Hamiltonian, described in strings.
+            endianness: The endianness of the operators. Default is big. Qubit 0 is the most significant bit.
+            trainable: Whether the parameters are trainable.
+            theta: The initial value of theta.
+        
+        """
+        self.hamil = Hamiltonian(coeffs, paulis, endianness)
+        super().__init__(
+            hamil=self.hamil,
+            trainable=trainable,
+            theta=theta,
+        )
+        self.coeffs = coeffs
+        self.paulis = paulis
+        self.trainable = trainable
+    
+    def forward(self, qdev, wires):
+        """Forward the OpHamilExp module.
+        Args:
+            qdev: The QuantumDevice.
+            wires: The wires.
+
+        """
+        matrix = self.matrix.to(qdev.device)
+        if qdev.record_op:
+            qdev.op_history.append(
+            {
+                "name": self.__class__.__name__,  # type: ignore
+                "wires": np.array(wires).squeeze().tolist(),
+                "coeffs": self.coeffs,
+                "paulis": self.paulis, 
+                "inverse": False,
+                "trainable": self.trainable,
+                "params": self.theta.item(),
+            }
+        )
+        
+        tqf.qubitunitaryfast(
+            q_device=qdev,
+            wires=wires,
+            params=matrix,
+        )
diff --git a/torchquantum/operators.py b/torchquantum/operator/operators.py
similarity index 79%
rename from torchquantum/operators.py
rename to torchquantum/operator/operators.py
index 42d5de04..1d1d4b8b 100644
--- a/torchquantum/operators.py
+++ b/torchquantum/operator/operators.py
@@ -1,14 +1,38 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torch.nn as nn
 import torchquantum as tq
-import torchquantum.functional as tqf
+import torchquantum.functional.functionals as tqf
 import numpy as np
 
 from enum import IntEnum
 from torchquantum.functional import mat_dict
-from torchquantum.quantization.clifford_quantization import CliffordQuantizer
+from torchquantum.util.quantization.clifford_quantization import CliffordQuantizer
 from abc import ABCMeta
-from .macro import C_DTYPE, F_DTYPE
+from ..macro import C_DTYPE, F_DTYPE
 from torchpack.utils.logging import logger
 from typing import Iterable, Union, List
 
@@ -53,6 +77,7 @@
     "U1",
     "U2",
     "U3",
+    "CU",
     "CU1",
     "CU2",
     "CU3",
@@ -66,6 +91,28 @@
     "SingleExcitation",
     "EchoedCrossResonance",
     "ECR",
+    "QFT",
+    "SDG",
+    "TDG",
+    "SXDG",
+    "CH",
+    "CCZ",
+    "ISWAP",
+    "CS",
+    "CSDG",
+    "CSX",
+    "CHadamard",
+    "CCZ",
+    "DCX",
+    "XXMINYY",
+    "XXPLUSYY",
+    "C3X",
+    "R",
+    "C4X",
+    "RC3X",
+    "RCCX",
+    "GlobalPhase",
+    "C3SX",
 ]
 
 
@@ -122,6 +169,23 @@ class Operator(tq.QuantumModule):
         "MultiXCNOT",
         "Reset",
         "EchoedCrossResonance",
+        "QFT",
+        "SDG",
+        "TDG",
+        "SXDG",
+        "CH",
+        "CCZ",
+        "ISWAP",
+        "CS",
+        "CSDG",
+        "CSX",
+        "CHadamard",
+        "DCX",
+        "C3X",
+        "C3SX",
+        "RCCX",
+        "RC3X",
+        "C4X",
     ]
 
     parameterized_ops = [
@@ -142,6 +206,7 @@ class Operator(tq.QuantumModule):
         "U1",
         "U2",
         "U3",
+        "CU",
         "CU1",
         "CU2",
         "CU3",
@@ -150,6 +215,10 @@ class Operator(tq.QuantumModule):
         "TrainableUnitary",
         "TrainableUnitaryStrict",
         "SingleExcitation",
+        "XXMINYY",
+        "XXPLUSYY",
+        "R",
+        "GlobalPhase",
     ]
 
     @property
@@ -174,7 +243,7 @@ def __init__(
         init_params=None,
         n_wires=None,
         wires=None,
-        inverse=False
+        inverse=False,
     ):
         """__init__ function for Operator.
 
@@ -379,7 +448,7 @@ def __init__(
         inverse=False,
     ):
         """Init function of the Observable class
-        
+
         Args:
             has_params (bool, optional): Whether the operations has parameters.
                 Defaults to False.
@@ -397,7 +466,7 @@ def __init__(
             init_params=init_params,
             n_wires=n_wires,
             wires=wires,
-            inverse=inverse
+            inverse=inverse,
         )
         self.return_type = None
 
@@ -420,7 +489,7 @@ def __init__(
         init_params=None,
         n_wires=None,
         wires=None,
-        inverse=False
+        inverse=False,
     ):
         """_summary_
 
@@ -441,7 +510,7 @@ def __init__(
             init_params=init_params,
             n_wires=n_wires,
             wires=wires,
-            inverse=inverse
+            inverse=inverse,
         )
         if type(self.num_wires) == int:
             self.n_wires = self.num_wires
@@ -1043,6 +1112,18 @@ def _matrix(cls, params):
         return tqf.u1_matrix(params)
 
 
+class CU(Operation, metaclass=ABCMeta):
+    """Class for Controlled U gate (4-parameter two-qubit gate)."""
+
+    num_params = 4
+    num_wires = 2
+    func = staticmethod(tqf.cu)
+
+    @classmethod
+    def _matrix(cls, params):
+        return tqf.cu_matrix(params)
+
+
 class CU1(DiagonalOperation, metaclass=ABCMeta):
     """Class for controlled U1 gate."""
 
@@ -1318,10 +1399,294 @@ def _matrix(cls, params):
         return cls.matrix
 
 
+class QFT(Observable, metaclass=ABCMeta):
+    """Class for Quantum Fourier Transform."""
+
+    num_params = 0
+    num_wires = AnyWires
+    func = staticmethod(tqf.qft)
+
+    @classmethod
+    def _matrix(cls, params, n_wires):
+        return tqf.qft_matrix(n_wires)
+
+
+class SDG(Operation, metaclass=ABCMeta):
+    """Class for SDG Gate."""
+
+    num_params = 0
+    num_wires = 1
+
+    matrix = mat_dict["sdg"]
+    func = staticmethod(tqf.sdg)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class TDG(Operation, metaclass=ABCMeta):
+    """Class for TDG Gate."""
+
+    num_params = 0
+    num_wires = 1
+    matrix = mat_dict["tdg"]
+    func = staticmethod(tqf.tdg)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class SXDG(Operation, metaclass=ABCMeta):
+    """Class for SXDG Gate."""
+
+    num_params = 0
+    num_wires = 1
+    matrix = mat_dict["sxdg"]
+    func = staticmethod(tqf.sxdg)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class CCZ(Operation, metaclass=ABCMeta):
+    """Class for CCZ Gate."""
+
+    num_params = 0
+    num_wires = 3
+    matrix = mat_dict["ccz"]
+    func = staticmethod(tqf.ccz)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class ISWAP(Operation, metaclass=ABCMeta):
+    """Class for ISWAP Gate."""
+
+    num_params = 0
+    num_wires = 2
+    matrix = mat_dict["iswap"]
+    func = staticmethod(tqf.iswap)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class CS(Operation, metaclass=ABCMeta):
+    """Class for CS Gate."""
+
+    num_params = 0
+    num_wires = 2
+    matrix = mat_dict["cs"]
+    eigvals = np.array([1, 1, 1, 1j])
+    func = staticmethod(tqf.cs)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+    @classmethod
+    def _eigvals(cls, params):
+        return cls.eigvals
+
+
+class CSDG(DiagonalOperation, metaclass=ABCMeta):
+    """Class for CS Dagger Gate."""
+
+    num_params = 0
+    num_wires = 2
+    matrix = mat_dict["csdg"]
+    eigvals = np.array([1, 1, 1, -1j])
+    func = staticmethod(tqf.csdg)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+    @classmethod
+    def _eigvals(cls, params):
+        return cls.eigvals
+
+
+class CSX(Operation, metaclass=ABCMeta):
+    """Class for CSX Gate."""
+
+    num_params = 0
+    num_wires = 2
+    matrix = mat_dict["csx"]
+    func = staticmethod(tqf.csx)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class CHadamard(Operation, metaclass=ABCMeta):
+    """Class for CHadamard Gate."""
+
+    num_params = 0
+    num_wires = 2
+    matrix = mat_dict["chadamard"]
+    func = staticmethod(tqf.chadamard)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class CCZ(DiagonalOperation, metaclass=ABCMeta):
+    """Class for CCZ Gate."""
+
+    num_params = 0
+    num_wires = 3
+    matrix = mat_dict["ccz"]
+    eigvals = np.array([1, 1, 1, 1, 1, 1, 1, -1])
+    func = staticmethod(tqf.ccz)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+    @classmethod
+    def _eigvals(cls, params):
+        return cls.eigvals
+
+
+class DCX(Operation, metaclass=ABCMeta):
+    """Class for DCX Gate."""
+
+    num_params = 0
+    num_wires = 2
+    matrix = mat_dict["dcx"]
+    func = staticmethod(tqf.dcx)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class XXMINYY(Operation, metaclass=ABCMeta):
+    """Class for XXMinusYY gate."""
+
+    num_params = 2
+    num_wires = 2
+    func = staticmethod(tqf.xxminyy_matrix)
+
+    @classmethod
+    def _matrix(cls, params):
+        return tqf.xxminyy_matrix(params)
+
+
+class XXPLUSYY(Operation, metaclass=ABCMeta):
+    """Class for XXPlusYY gate."""
+
+    num_params = 2
+    num_wires = 2
+    func = staticmethod(tqf.xxplusyy_matrix)
+
+    @classmethod
+    def _matrix(cls, params):
+        return tqf.xxplusyy_matrix(params)
+
+
+class C3X(Operation, metaclass=ABCMeta):
+    """Class for C3X gate."""
+
+    num_params = 0
+    num_wires = 4
+    matrix = mat_dict["c3x"]
+    func = staticmethod(tqf.c3x)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class R(DiagonalOperation, metaclass=ABCMeta):
+    """Class for R Gate."""
+
+    num_params = 2
+    num_wires = 1
+    func = staticmethod(tqf.r)
+
+    @classmethod
+    def _matrix(cls, params):
+        return tqf.r_matrix(params)
+
+
+class C4X(Operation, metaclass=ABCMeta):
+    """Class for C4X Gate."""
+
+    num_params = 0
+    num_wires = 5
+    matrix = mat_dict["c4x"]
+    func = staticmethod(tqf.c4x)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class RC3X(Operation, metaclass=ABCMeta):
+    """Class for RC3X Gate."""
+
+    num_params = 0
+    num_wires = 4
+    matrix = mat_dict["rc3x"]
+    func = staticmethod(tqf.rc3x)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class RCCX(Operation, metaclass=ABCMeta):
+    """Class for RCCX Gate."""
+
+    num_params = 0
+    num_wires = 3
+    matrix = mat_dict["rccx"]
+    func = staticmethod(tqf.rccx)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
+class GlobalPhase(Operation, metaclass=ABCMeta):
+    """Class for Global Phase gate."""
+
+    num_params = 1
+    num_wires = 0
+    func = staticmethod(tqf.globalphase)
+
+    @classmethod
+    def _matrix(cls, params):
+        return tqf.globalphase_matrix(params)
+
+
+class C3SX(Operation, metaclass=ABCMeta):
+    """Class for C3SX Gate."""
+
+    num_params = 0
+    num_wires = 4
+    matrix = mat_dict["c3sx"]
+    func = staticmethod(tqf.c3sx)
+
+    @classmethod
+    def _matrix(cls, params):
+        return cls.matrix
+
+
 H = Hadamard
 SH = SHadamard
 EchoedCrossResonance = ECR
-
+CH = CHadamard
 
 op_name_dict = {
     "hadamard": Hadamard,
@@ -1376,7 +1741,7 @@ def _matrix(cls, params):
     "cphase": CU1,
     "cu2": CU2,
     "cu3": CU3,
-    "cu": CU3,
+    "cu": CU,
     "qubitunitary": QubitUnitary,
     "qubitunitarystrict": QubitUnitaryFast,
     "qubitunitaryfast": QubitUnitaryFast,
@@ -1388,4 +1753,26 @@ def _matrix(cls, params):
     "singleexcitation": SingleExcitation,
     "ecr": ECR,
     "echoedcrossresonance": ECR,
+    "QFT": QFT,
+    "sdg": SDG,
+    "cs": CS,
+    "chadamard": CHadamard,
+    "ch": CH,
+    "dcx": DCX,
+    "xxminyy": XXMINYY,
+    "xxplusyy": XXPLUSYY,
+    "c3x": C3X,
+    "tdg": TDG,
+    "sxdg": SXDG,
+    "ch": CH,
+    "ccz": CCZ,
+    "iswap": ISWAP,
+    "csdg": CSDG,
+    "csx": CSX,
+    "r": R,
+    "c3sx": C3SX,
+    "globalphase": GlobalPhase,
+    "rccx": RCCX,
+    "rc3x": RC3X,
+    "c4x": C4X,
 }
diff --git a/torchquantum/plugin/__init__.py b/torchquantum/plugin/__init__.py
new file mode 100644
index 00000000..45756475
--- /dev/null
+++ b/torchquantum/plugin/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .qiskit import *
diff --git a/torchquantum/plugin/qiskit/__init__.py b/torchquantum/plugin/qiskit/__init__.py
new file mode 100644
index 00000000..e15b49d9
--- /dev/null
+++ b/torchquantum/plugin/qiskit/__init__.py
@@ -0,0 +1,29 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .qiskit_macros import *
+from .qiskit_plugin import *
+from .qiskit_pulse import *
+from .qiskit_processor import *
+from .qiskit_unitary_gate import *
diff --git a/torchquantum/plugins/aerbackend_fixed.py b/torchquantum/plugin/qiskit/aerbackend_fixed.py
similarity index 100%
rename from torchquantum/plugins/aerbackend_fixed.py
rename to torchquantum/plugin/qiskit/aerbackend_fixed.py
diff --git a/torchquantum/plugin/qiskit/fix_qiskit_parameterization.py b/torchquantum/plugin/qiskit/fix_qiskit_parameterization.py
new file mode 100644
index 00000000..cbf49f2a
--- /dev/null
+++ b/torchquantum/plugin/qiskit/fix_qiskit_parameterization.py
@@ -0,0 +1,53 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import qiskit
+import os
+import shutil
+
+if __name__ == "__main__":
+    path = os.path.abspath(qiskit.__file__)
+    print(path)
+    # path for aer provider
+    path_provider = path.replace("__init__.py", "providers/aer/backends/aerbackend.py")
+    print(path_provider)
+    fixed_file = "aerbackend_fixed.py"
+
+    with open(path_provider, "r") as fid:
+        for line in fid.readlines():
+            if "FIXED" in line:
+                print("The qiskit parameterization bug is already fixed!")
+                exit(0)
+            else:
+                print(
+                    f"Fixing the qiskit parameterization bug by replacing "
+                    f"the {path_provider} file with {fixed_file}!"
+                )
+                break
+
+    shutil.copyfile(
+        path_provider, path_provider.replace("aerbackend", "aerbackend.orig")
+    )
+    shutil.copyfile(fixed_file, path_provider)
+    print("Finished!")
diff --git a/torchquantum/plugins/my_job_monitor.py b/torchquantum/plugin/qiskit/my_job_monitor.py
similarity index 100%
rename from torchquantum/plugins/my_job_monitor.py
rename to torchquantum/plugin/qiskit/my_job_monitor.py
diff --git a/torchquantum/plugin/qiskit/qiskit_macros.py b/torchquantum/plugin/qiskit/qiskit_macros.py
new file mode 100644
index 00000000..71e8e463
--- /dev/null
+++ b/torchquantum/plugin/qiskit/qiskit_macros.py
@@ -0,0 +1,84 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torchquantum as tq
+
+QISKIT_INCOMPATIBLE_OPS = [
+    tq.Rot,
+    tq.MultiRZ,
+    tq.CRot,
+]
+
+QISKIT_INCOMPATIBLE_FUNC_NAMES = [
+    "rot",
+    "multirz",
+    "crot",
+]
+
+IBMQ_NAMES = [
+    "ibmqx2",
+    "ibmq_16_melbourne",
+    "ibmq_5_yorktown",
+    "ibmq_armonk",
+    "ibmq_athens",
+    "ibmq_belem",
+    "ibmq_bogota",
+    "ibmq_casablanca",
+    "ibmq_dublin",
+    "ibmq_guadalupe",
+    "ibmq_jakarta",
+    "ibmq_kolkata",
+    "ibmq_lima",
+    "ibmq_manhattan",
+    "ibmq_manila",
+    "ibmq_montreal",
+    "ibmq_mumbai",
+    "ibmq_paris",
+    "ibmq_qasm_simulator",
+    "ibmq_quito",
+    "ibmq_rome",
+    "ibmq_santiago",
+    "ibmq_sydney",
+    "ibmq_toronto",
+    "simulator_extended_stabilizer",
+    "simulator_mps",
+    "simulator_stabilizer",
+    "simulator_statevector",
+    "ibm_auckland",
+    "ibm_cairo",
+    "ibm_geneva",
+    "ibm_hanoi",
+    "ibm_ithaca",
+    "ibm_lagos",
+    "ibm_nairobi",
+    "ibm_oslo",
+    "ibm_peekskill",
+    "ibm_perth",
+    "ibm_washington",
+]
+
+IBMQ_PNAMES = [
+    "FakeArmonk",
+    "FakeBogota" "FakeQuito",
+]
diff --git a/torchquantum/plugins/qiskit_plugin.py b/torchquantum/plugin/qiskit/qiskit_plugin.py
similarity index 95%
rename from torchquantum/plugins/qiskit_plugin.py
rename to torchquantum/plugin/qiskit/qiskit_plugin.py
index c412d92b..e407ada3 100644
--- a/torchquantum/plugins/qiskit_plugin.py
+++ b/torchquantum/plugin/qiskit/qiskit_plugin.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torchquantum as tq
 import torchquantum.functional as tqf
@@ -8,7 +32,7 @@
 from qiskit import Aer, execute
 from qiskit.circuit import Parameter
 from torchpack.utils.logging import logger
-from torchquantum.utils import (
+from torchquantum.util import (
     switch_little_big_endian_matrix,
     find_global_phase,
     switch_little_big_endian_state,
@@ -250,7 +274,7 @@ def append_fixed_gate(circ, func, params, wires, inverse):
         circ.swap(*wires)
     elif func == "sswap":
         # square root of swap
-        from torchquantum.plugins.qiskit_unitary_gate import UnitaryGate
+        from torchquantum.plugin.qiskit_unitary_gate import UnitaryGate
 
         mat = mat_dict["sswap"].detach().cpu().numpy()
         mat = switch_little_big_endian_matrix(mat)
@@ -284,7 +308,7 @@ def append_fixed_gate(circ, func, params, wires, inverse):
         or func == "qubitunitaryfast"
         or func == "qubitunitarystrict"
     ):
-        from torchquantum.plugins.qiskit_unitary_gate import UnitaryGate
+        from torchquantum.plugin.qiskit_unitary_gate import UnitaryGate
 
         mat = np.array(params)
         mat = switch_little_big_endian_matrix(mat)
@@ -488,7 +512,7 @@ def tq2qiskit(
             circ.swap(*module.wires)
         elif module.name == "SSWAP":
             # square root of swap
-            from torchquantum.plugins.qiskit_unitary_gate import UnitaryGate
+            from torchquantum.plugin.qiskit_unitary_gate import UnitaryGate
 
             mat = module.matrix.data.cpu().numpy()
             mat = switch_little_big_endian_matrix(mat)
@@ -523,7 +547,7 @@ def tq2qiskit(
             or module.name == "TrainableUnitary"
             or module.name == "TrainableUnitaryStrict"
         ):
-            from torchquantum.plugins.qiskit_unitary_gate import UnitaryGate
+            from torchquantum.plugin.qiskit_unitary_gate import UnitaryGate
 
             mat = module.params[0].data.cpu().numpy()
             mat = switch_little_big_endian_matrix(mat)
diff --git a/torchquantum/plugins/qiskit_processor.py b/torchquantum/plugin/qiskit/qiskit_processor.py
similarity index 95%
rename from torchquantum/plugins/qiskit_processor.py
rename to torchquantum/plugin/qiskit/qiskit_processor.py
index 83aa2539..2d91e7c3 100644
--- a/torchquantum/plugins/qiskit_processor.py
+++ b/torchquantum/plugin/qiskit/qiskit_processor.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torch
 import torchquantum as tq
 import pathos.multiprocessing as multiprocessing
@@ -7,25 +31,25 @@
 from qiskit.providers.aer.noise import NoiseModel
 from qiskit.tools.monitor import job_monitor
 from qiskit.exceptions import QiskitError
-from torchquantum.plugins import (
+from .qiskit_plugin import (
     tq2qiskit,
     tq2qiskit_parameterized,
     tq2qiskit_measurement,
 )
-from torchquantum.utils import (
+from torchquantum.util import (
     get_expectations_from_counts,
     get_provider,
     get_provider_hub_group_project,
     get_circ_stats,
 )
-from torchquantum.plugins.qiskit_macros import IBMQ_NAMES
+from .qiskit_macros import IBMQ_NAMES
 from tqdm import tqdm
 from torchpack.utils.logging import logger
 from qiskit.transpiler import PassManager
 import numpy as np
 import datetime
 
-from torchquantum.plugins import my_job_monitor
+from .my_job_monitor import my_job_monitor
 
 
 class EmptyPassManager(PassManager):
@@ -715,7 +739,7 @@ def process_ready_circs_get_counts(self, circs_all, parallel=True):
             job_monitor(job, interval=1)
 
             result = job.result()
-            counts = result.get_counts()
+            counts = [result.get_counts()]
         return counts
 
     def process_ready_circs(self, q_device, circs_all, parallel=True):
diff --git a/torchquantum/plugin/qiskit/qiskit_pulse.py b/torchquantum/plugin/qiskit/qiskit_pulse.py
new file mode 100644
index 00000000..b9c78760
--- /dev/null
+++ b/torchquantum/plugin/qiskit/qiskit_pulse.py
@@ -0,0 +1,41 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torchquantum as tq
+from qiskit import pulse, QuantumCircuit
+from qiskit.pulse import library
+from qiskit.test.mock import FakeQuito, FakeArmonk, FakeBogota
+from qiskit.compiler import assemble, schedule
+from .qiskit_macros import IBMQ_PNAMES
+
+
+def circ2pulse(circuits, name):
+    if name in IBMQ_PNAMES:
+        backend = name()
+        with pulse.build(backend) as pulse_tq:
+            qc = circuits
+            qc.measure_all()
+            pulse.call(qc)
+        pulse_tq.draw()
diff --git a/torchquantum/plugins/qiskit_unitary_gate.py b/torchquantum/plugin/qiskit/qiskit_unitary_gate.py
similarity index 100%
rename from torchquantum/plugins/qiskit_unitary_gate.py
rename to torchquantum/plugin/qiskit/qiskit_unitary_gate.py
diff --git a/torchquantum/plugins/qiskit_pulse.py b/torchquantum/plugin/qiskit_pulse.py
similarity index 57%
rename from torchquantum/plugins/qiskit_pulse.py
rename to torchquantum/plugin/qiskit_pulse.py
index 17e32cf9..81775b0d 100644
--- a/torchquantum/plugins/qiskit_pulse.py
+++ b/torchquantum/plugin/qiskit_pulse.py
@@ -8,6 +8,23 @@
 
 
 def circ2pulse(circuits, name):
+    """
+    Convert a circuit to a pulse schedule using the specified backend.
+
+    Args:
+        circuits (QuantumCircuit): The input quantum circuit.
+        name (str): The name of the backend.
+
+    Returns:
+        None.
+
+    Example:
+        >>> qc = QuantumCircuit(2)
+        >>> qc.h(0)
+        >>> qc.cx(0, 1)
+        >>> circ2pulse(qc, 'ibmq_oslo')
+    """
+    
     if name in IBMQ_PNAMES:
         backend = name()
         with pulse.build(backend) as pulse_tq:
diff --git a/torchquantum/plugins/__init__.py b/torchquantum/plugins/__init__.py
deleted file mode 100644
index 305e76c3..00000000
--- a/torchquantum/plugins/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .qiskit_plugin import *
-from .qiskit_processor import *
-from .my_job_monitor import *
diff --git a/torchquantum/plugins/fix_qiskit_parameterization.py b/torchquantum/plugins/fix_qiskit_parameterization.py
deleted file mode 100644
index 4dded65e..00000000
--- a/torchquantum/plugins/fix_qiskit_parameterization.py
+++ /dev/null
@@ -1,29 +0,0 @@
-import qiskit
-import os
-import shutil
-
-if __name__ == "__main__":
-    path = os.path.abspath(qiskit.__file__)
-    print(path)
-    # path for aer provider
-    path_provider = path.replace("__init__.py", "providers/aer/backends/aerbackend.py")
-    print(path_provider)
-    fixed_file = "aerbackend_fixed.py"
-
-    with open(path_provider, "r") as fid:
-        for line in fid.readlines():
-            if "FIXED" in line:
-                print("The qiskit parameterization bug is already fixed!")
-                exit(0)
-            else:
-                print(
-                    f"Fixing the qiskit parameterization bug by replacing "
-                    f"the {path_provider} file with {fixed_file}!"
-                )
-                break
-
-    shutil.copyfile(
-        path_provider, path_provider.replace("aerbackend", "aerbackend.orig")
-    )
-    shutil.copyfile(fixed_file, path_provider)
-    print("Finished!")
diff --git a/torchquantum/plugins/qiskit_macros.py b/torchquantum/plugins/qiskit_macros.py
deleted file mode 100644
index 3d9a2aa1..00000000
--- a/torchquantum/plugins/qiskit_macros.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import torchquantum as tq
-
-QISKIT_INCOMPATIBLE_OPS = [
-    tq.Rot,
-    tq.MultiRZ,
-    tq.CRot,
-]
-
-QISKIT_INCOMPATIBLE_FUNC_NAMES = [
-    "rot",
-    "multirz",
-    "crot",
-]
-
-IBMQ_NAMES = [
-    "ibmqx2",
-    "ibmq_16_melbourne",
-    "ibmq_5_yorktown",
-    "ibmq_armonk",
-    "ibmq_athens",
-    "ibmq_belem",
-    "ibmq_bogota",
-    "ibmq_casablanca",
-    "ibmq_dublin",
-    "ibmq_guadalupe",
-    "ibmq_jakarta",
-    "ibmq_kolkata",
-    "ibmq_lima",
-    "ibmq_manhattan",
-    "ibmq_manila",
-    "ibmq_montreal",
-    "ibmq_mumbai",
-    "ibmq_paris",
-    "ibmq_qasm_simulator",
-    "ibmq_quito",
-    "ibmq_rome",
-    "ibmq_santiago",
-    "ibmq_sydney",
-    "ibmq_toronto",
-    "simulator_extended_stabilizer",
-    "simulator_mps",
-    "simulator_stabilizer",
-    "simulator_statevector",
-    "ibm_auckland",
-    "ibm_cairo",
-    "ibm_geneva",
-    "ibm_hanoi",
-    "ibm_ithaca",
-    "ibm_lagos",
-    "ibm_nairobi",
-    "ibm_oslo",
-    "ibm_peekskill",
-    "ibm_perth",
-    "ibm_washington",
-]
-
-IBMQ_PNAMES = [
-    "FakeArmonk",
-    "FakeBogota" "FakeQuito",
-]
diff --git a/torchquantum/pulse.py b/torchquantum/pulse.py
deleted file mode 100644
index 33543f2d..00000000
--- a/torchquantum/pulse.py
+++ /dev/null
@@ -1,145 +0,0 @@
-import torch
-import torch.nn as nn
-import numpy as np
-
-from typing import Union, List, Iterable
-
-
-__all__ = [
-    "QuantumPulse",
-    "QuantumPulseGaussian",
-    "QuantumPulseDirect",
-]
-
-
-class QuantumPulse(nn.Module):
-    """
-    The Quantum Pulse simulator
-    """
-
-    def __init__(self):
-        super().__init__()
-        pass
-
-    def forward(self):
-        pass
-
-
-class QuantumPulseDirect(QuantumPulse):
-    def __init__(
-        self,
-        n_steps: int,
-        hamil,
-        delta_t: float = 1.0,
-        initial_shape: List[float] = None,
-    ):
-        super().__init__()
-        self.hamil = torch.tensor(hamil, dtype=torch.complex64)
-        if initial_shape is not None:
-            assert len(initial_shape) == n_steps
-            initial_shape = torch.Tensor(initial_shape)
-        else:
-            initial_shape = torch.ones(n_steps)
-        self.pulse_shape = nn.Parameter(initial_shape)
-        self.n_steps = n_steps
-        self.delta_t = delta_t
-
-    def get_unitary(self):
-        unitary_per_step = []
-        for k in range(self.n_steps):
-            magnitude = self.pulse_shape[k]
-            unitary = torch.matrix_exp(-1j * self.hamil * magnitude * self.delta_t)
-            # print(unitary @ unitary.conj().T)
-            # unitary_mag = (unitary[0]**2).sum().sqrt()
-            # unitary = unitary_mag / unitary
-
-            unitary_per_step.append(unitary)
-
-        u_overall = None
-        for k, u in enumerate(unitary_per_step):
-            if not k:
-                u_overall = u
-            else:
-                u_overall = u_overall @ u
-
-        return u_overall
-
-    def __repr__(self):
-        return f"QuantumPulse Direct \n shape: {self.pulse_shape}"
-
-
-class QuantumPulseGaussian(QuantumPulse):
-    """Gaussian Quantum Pulse, will only count +- five sigmas"""
-
-    def __init__(
-        self,
-        hamil,
-        n_steps: int = 100,
-        delta_t: float = 1.0,
-        x_min: float = -10,
-        x_max: float = 10,
-        initial_params: List[float] = None,
-    ):
-        super(QuantumPulseGaussian, self).__init__()
-        self.hamil = torch.tensor(hamil, dtype=torch.complex64)
-        self.delta_t = delta_t
-        # mag, mu, sigma
-        if initial_params is not None:
-            assert len(initial_params) == 3
-            initial_params = torch.Tensor(initial_params)
-        else:
-            initial_params = torch.ones(3)
-
-        self.pulse_params = nn.Parameter(initial_params)
-        self.n_steps = n_steps
-        self.delta_x = (x_max - x_min) / n_steps
-        self.x_list = torch.tensor(np.arange(x_min, x_max, self.delta_x))
-
-    def get_unitary(self):
-        self.mag = self.pulse_params[0]
-        self.mu = self.pulse_params[1]
-        self.sigma = self.pulse_params[2]
-
-        # delta_x = (10 * self.sigma / self.n_steps).item()
-        # self.x_list = torch.tensor(np.arange(
-        # (self.mu - 5 * self.sigma).item(),
-        # (self.mu + 5 * self.sigma).item(), delta_x))
-
-        self.pulse_shape = self.mag * torch.exp(
-            -((self.x_list - self.mu) ** 2) / (2 * self.sigma**2)
-        )
-
-        unitary_per_step = []
-        for k in range(self.n_steps):
-            magnitude = self.pulse_shape[k]
-            unitary = torch.matrix_exp(
-                -1j * self.hamil * magnitude * self.delta_t * self.delta_x
-            )
-            # print(unitary @ unitary.conj().T)
-            # unitary_mag = (unitary[0]**2).sum().sqrt()
-            # unitary = unitary_mag / unitary
-
-            unitary_per_step.append(unitary)
-
-        u_overall = None
-        for k, u in enumerate(unitary_per_step):
-            if not k:
-                u_overall = u
-            else:
-                u_overall = u_overall @ u
-
-        return u_overall
-
-    def __repr__(self):
-        return f"QuantumPulse Guassian \n shape: {self.pulse_shape}"
-
-
-if __name__ == "__main__":
-    import pdb
-
-    pdb.set_trace()
-    pulse = QuantumPulseDirect(n_steps=10, hamil=[[0, 1], [1, 0]])
-
-    print(pulse.get_unitary())
-
-    print("finish")
diff --git a/torchquantum/pulse/__init__.py b/torchquantum/pulse/__init__.py
index 3f785775..5a4539de 100644
--- a/torchquantum/pulse/__init__.py
+++ b/torchquantum/pulse/__init__.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 from .utils import *
 from .sesolve import sesolve
 from .mesolve import mesolve
diff --git a/torchquantum/pulse_utils.py b/torchquantum/pulse/pulse_utils.py
similarity index 58%
rename from torchquantum/pulse_utils.py
rename to torchquantum/pulse/pulse_utils.py
index bad2a9b5..68c66568 100644
--- a/torchquantum/pulse_utils.py
+++ b/torchquantum/pulse/pulse_utils.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import copy
 import sched
 import qiskit
@@ -38,6 +62,16 @@
 
 
 def is_parametric_pulse(t0, *inst: Union["Schedule", Instruction]):
+    """
+        Check if the instruction is a parametric pulse.
+
+        Args:
+            t0 (tuple): Tuple containing the time and instruction.
+            inst (tuple): Tuple containing the instruction.
+
+        Returns:
+            bool: True if the instruction is a parametric pulse, False otherwise.
+        """
     inst = t0[1]
     t0 = t0[0]
     if isinstance(inst, pulse.Play):
@@ -47,6 +81,15 @@ def is_parametric_pulse(t0, *inst: Union["Schedule", Instruction]):
 
 
 def extract_ampreal(pulse_prog):
+    """
+       Extract the real part of pulse amplitudes from the pulse program.
+
+       Args:
+           pulse_prog (Schedule): The pulse program.
+
+       Returns:
+           np.array: Array of real parts of pulse amplitudes.
+       """
     # extract the real part of pulse amplitude, igonred the imaginary part.
     amp_list = list(
         map(
@@ -60,6 +103,15 @@ def extract_ampreal(pulse_prog):
 
 
 def extract_amp(pulse_prog):
+    """
+        Extract the pulse amplitudes from the pulse program.
+
+        Args:
+            pulse_prog (Schedule): The pulse program.
+
+        Returns:
+            np.array: Array of pulse amplitudes.
+        """
     # extract the pulse amplitdue.
     amp_list = list(
         map(
@@ -79,6 +131,16 @@ def extract_amp(pulse_prog):
 
 
 def is_phase_pulse(t0, *inst: Union["Schedule", Instruction]):
+    """
+        Check if the instruction is a phase pulse.
+
+        Args:
+            t0 (tuple): Tuple containing the time and instruction.
+            inst (tuple): Tuple containing the instruction.
+
+        Returns:
+            bool: True if the instruction is a phase pulse, False otherwise.
+        """
     inst = t0[1]
     t0 = t0[0]
     if isinstance(inst, pulse.ShiftPhase):
@@ -87,6 +149,15 @@ def is_phase_pulse(t0, *inst: Union["Schedule", Instruction]):
 
 
 def extract_phase(pulse_prog):
+    """
+        Extract the phase values from the pulse program.
+
+        Args:
+            pulse_prog (Schedule): The pulse program.
+
+        Returns:
+            list: List of phase values.
+        """
 
     for _, ShiftPhase in pulse_prog.filter(is_phase_pulse).instructions:
         # print(play.pulse.amp)
@@ -103,6 +174,16 @@ def extract_phase(pulse_prog):
 
 
 def cir2pul(circuit, backend):
+    """
+        Transform a quantum circuit to a pulse schedule.
+
+        Args:
+            circuit (QuantumCircuit): The quantum circuit.
+            backend: The backend for the pulse schedule.
+
+        Returns:
+            Schedule: The pulse schedule.
+        """
     # transform quantum circuit to pulse schedule
     with pulse.build(backend) as pulse_prog:
         pulse.call(circuit)
@@ -110,6 +191,16 @@ def cir2pul(circuit, backend):
 
 
 def snp(qubit, backend):
+    """
+        Create a Schedule for the simultaneous z measurement of a qubit and a control qubit.
+
+        Args:
+            qubit (int): The target qubit.
+            backend: The backend for the pulse schedule.
+
+        Returns:
+            Schedule: The pulse schedule for simultaneous z measurement.
+        """
     circuit = QuantumCircuit(qubit + 1)
     circuit.h(qubit)
     sched = cir2pul(circuit, backend)
@@ -118,6 +209,17 @@ def snp(qubit, backend):
 
 
 def tnp(qubit, cqubit, backend):
+    """
+        Create a Schedule for the simultaneous controlled-x measurement of a qubit and a control qubit.
+
+        Args:
+            qubit (int): The target qubit.
+            cqubit (int): The control qubit.
+            backend: The backend for the pulse schedule.
+
+        Returns:
+            Schedule: The pulse schedule for simultaneous controlled-x measurement.
+        """
     circuit = QuantumCircuit(cqubit + 1)
     circuit.cx(qubit, cqubit)
     sched = cir2pul(circuit, backend)
@@ -126,11 +228,31 @@ def tnp(qubit, cqubit, backend):
 
 
 def pul_append(sched1, sched2):
+    """
+        Append two pulse schedules.
+
+        Args:
+            sched1 (Schedule): The first pulse schedule.
+            sched2 (Schedule): The second pulse schedule.
+
+        Returns:
+            Schedule: The combined pulse schedule.
+        """
     sched = sched1.append(sched2)
     return sched
 
 
 def map_amp(pulse_ansatz, modified_list):
+    """
+        Map modified pulse amplitudes to the pulse ansatz.
+
+        Args:
+            pulse_ansatz (Schedule): The pulse ansatz.
+            modified_list (list): List of modified pulse amplitudes.
+
+        Returns:
+            Schedule: The pulse schedule with modified amplitudes.
+        """
     sched = Schedule()
     for inst, amp in zip(
         pulse_ansatz.filter(is_parametric_pulse).instructions, modified_list
@@ -151,6 +273,15 @@ def get_from(d: dict, key: str):
 
 
 def run_pulse_sim(measurement_pulse):
+    """
+        Run pulse simulations for the given measurement pulses.
+
+        Args:
+            measurement_pulse (list): List of measurement pulses.
+
+        Returns:
+            list: List of measurement results.
+        """
     measure_result = []
     for measure_pulse in measurement_pulse:
         shots = 1024
@@ -174,6 +305,15 @@ def run_pulse_sim(measurement_pulse):
 
 
 def gen_LC(parameters_array):
+    """
+        Generate linear constraints for the optimization.
+
+        Args:
+            parameters_array (np.array): Array of parameters.
+
+        Returns:
+            LinearConstraint: Linear constraint for the optimization.
+        """
     dim_design = int(len(parameters_array))
     Mid = int(len(parameters_array) / 2)
     bound = np.ones((dim_design, 2)) * np.array([0, 0.9])
@@ -186,6 +326,16 @@ def gen_LC(parameters_array):
 
 
 def observe_genearte(pulse_ansatz, backend):
+    """
+        Generate measurement pulses for observing the pulse ansatz.
+
+        Args:
+            pulse_ansatz (Schedule): The pulse ansatz.
+            backend: The backend for the pulse schedule.
+
+        Returns:
+            list: List of measurement pulses.
+        """
     qubits = 0, 1
     with pulse.build(backend) as pulse_measurez0:
         # z measurement of qubit 0 and 1
diff --git a/torchquantum/pulse/pulses.py b/torchquantum/pulse/pulses.py
new file mode 100644
index 00000000..942984ad
--- /dev/null
+++ b/torchquantum/pulse/pulses.py
@@ -0,0 +1,266 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torch.nn as nn
+import numpy as np
+
+from typing import Union, List, Iterable
+
+
+__all__ = [
+    "QuantumPulse",
+    "QuantumPulseGaussian",
+    "QuantumPulseDirect",
+]
+
+
+class QuantumPulse(nn.Module):
+    """The Quantum Pulse simulator
+    
+    Methods:
+        __init__(self):
+            Initialize the QuantumPulse.
+        forward(self)
+    """
+
+    def __init__(self):
+        """Initialize the Quantum Pulse simulator.
+        
+        Returns:
+            None.
+        """
+        
+        super().__init__()
+        pass
+
+    def forward(self):
+        pass
+
+
+class QuantumPulseDirect(QuantumPulse):
+    def __init__(
+        self,
+        n_steps: int,
+        hamil,
+        delta_t: float = 1.0,
+        initial_shape: List[float] = None,
+    ):
+        """Initializes a QuantumPulseDirect object.
+
+        Args:
+            n_steps (int): The number of time steps.
+            hamil: The Hamiltonian.
+            delta_t (float, optional): The time step size.
+                Defaults to 1.0.
+            initial_shape (List[float], optional): The initial shape of the pulse. 
+                Defaults to None.
+
+        Raises:
+            AssertionError: If the length of initial_shape is not equal to n_steps.
+
+        Example:
+            >>> hamiltonian = ...
+            >>> pulse = QuantumPulseDirect(n_steps=10, hamil=hamiltonian, delta_t=0.1)
+        """
+        
+        super().__init__()
+        self.hamil = torch.tensor(hamil, dtype=torch.complex64)
+        if initial_shape is not None:
+            assert len(initial_shape) == n_steps
+            initial_shape = torch.Tensor(initial_shape)
+        else:
+            initial_shape = torch.ones(n_steps)
+        self.pulse_shape = nn.Parameter(initial_shape)
+        self.n_steps = n_steps
+        self.delta_t = delta_t
+
+    def get_unitary(self):
+        """Computes the unitary evolution operator for the pulse.
+
+        Returns:
+            torch.Tensor: The unitary evolution operator.
+
+        Example:
+            >>> pulse = QuantumPulseDirect(n_steps=10, hamil=hamiltonian, delta_t=0.1)
+            >>> unitary = pulse.get_unitary()
+        """
+        
+        unitary_per_step = []
+        for k in range(self.n_steps):
+            magnitude = self.pulse_shape[k]
+            unitary = torch.matrix_exp(-1j * self.hamil * magnitude * self.delta_t)
+            # print(unitary @ unitary.conj().T)
+            # unitary_mag = (unitary[0]**2).sum().sqrt()
+            # unitary = unitary_mag / unitary
+
+            unitary_per_step.append(unitary)
+
+        u_overall = None
+        for k, u in enumerate(unitary_per_step):
+            if not k:
+                u_overall = u
+            else:
+                u_overall = u_overall @ u
+
+        return u_overall
+
+    def __repr__(self):
+        """Returns the string representation of the QuantumPulseDirect object.
+
+        Returns:
+            str: The string representation.
+
+        Example:
+            >>> pulse = QuantumPulseDirect(n_steps=10, hamil=hamiltonian, delta_t=0.1)
+            >>> print(pulse)
+            QuantumPulse Direct
+            shape: tensor([...])
+        """
+        
+        return f"QuantumPulse Direct \n shape: {self.pulse_shape}"
+
+
+class QuantumPulseGaussian(QuantumPulse):
+    """Gaussian Quantum Pulse, will only count +- five sigmas"""
+
+    def __init__(
+        self,
+        hamil,
+        n_steps: int = 100,
+        delta_t: float = 1.0,
+        x_min: float = -10,
+        x_max: float = 10,
+        initial_params: List[float] = None,
+    ):
+        """Initializes a QuantumPulseGaussian object.
+
+        Args:
+            hamil: The Hamiltonian.
+            n_steps (int, optional): The number of time steps.
+                Defaults to 100.
+            delta_t (float, optional): The time step size.
+                Defaults to 1.0.
+            x_min (float, optional): The minimum value of x.
+                Defaults to -10.
+            x_max (float, optional): The maximum value of x.
+                Defaults to 10.
+            initial_params (List[float], optional): The initial parameters of the pulse. 
+                Defaults to None.
+
+        Returns:
+            None.
+
+        Raises:
+            AssertionError: If the length of initial_params is not equal to 3.
+
+        Example:
+            >>> hamiltonian = ...
+            >>> pulse = QuantumPulseGaussian(hamil=hamiltonian, n_steps=100, delta_t=0.1)
+        """
+        
+        super(QuantumPulseGaussian, self).__init__()
+        self.hamil = torch.tensor(hamil, dtype=torch.complex64)
+        self.delta_t = delta_t
+        # mag, mu, sigma
+        if initial_params is not None:
+            assert len(initial_params) == 3
+            initial_params = torch.Tensor(initial_params)
+        else:
+            initial_params = torch.ones(3)
+
+        self.pulse_params = nn.Parameter(initial_params)
+        self.n_steps = n_steps
+        self.delta_x = (x_max - x_min) / n_steps
+        self.x_list = torch.tensor(np.arange(x_min, x_max, self.delta_x))
+
+    def get_unitary(self):
+        """Computes the unitary evolution operator for the pulse.
+
+        Returns:
+            torch.Tensor: The unitary evolution operator.
+
+        Example:
+            >>> pulse = QuantumPulseGaussian(hamil=hamiltonian, n_steps=100, delta_t=0.1)
+            >>> unitary = pulse.get_unitary()
+        """
+        
+        self.mag = self.pulse_params[0]
+        self.mu = self.pulse_params[1]
+        self.sigma = self.pulse_params[2]
+
+        # delta_x = (10 * self.sigma / self.n_steps).item()
+        # self.x_list = torch.tensor(np.arange(
+        # (self.mu - 5 * self.sigma).item(),
+        # (self.mu + 5 * self.sigma).item(), delta_x))
+
+        self.pulse_shape = self.mag * torch.exp(
+            -((self.x_list - self.mu) ** 2) / (2 * self.sigma**2)
+        )
+
+        unitary_per_step = []
+        for k in range(self.n_steps):
+            magnitude = self.pulse_shape[k]
+            unitary = torch.matrix_exp(
+                -1j * self.hamil * magnitude * self.delta_t * self.delta_x
+            )
+            # print(unitary @ unitary.conj().T)
+            # unitary_mag = (unitary[0]**2).sum().sqrt()
+            # unitary = unitary_mag / unitary
+
+            unitary_per_step.append(unitary)
+
+        u_overall = None
+        for k, u in enumerate(unitary_per_step):
+            if not k:
+                u_overall = u
+            else:
+                u_overall = u_overall @ u
+
+        return u_overall
+
+    def __repr__(self):
+        """Returns the string representation of the QuantumPulseGaussian object.
+
+        Returns:
+            str: The string representation.
+
+        Example:
+            >>> pulse = QuantumPulseGaussian(hamil=hamiltonian, n_steps=100, delta_t=0.1)
+            >>> print(pulse)
+            QuantumPulse Guassian
+            shape: tensor([...])
+        """
+        return f"QuantumPulse Guassian \n shape: {self.pulse_shape}"
+
+
+if __name__ == "__main__":
+    import pdb
+
+    pdb.set_trace()
+    pulse = QuantumPulseDirect(n_steps=10, hamil=[[0, 1], [1, 0]])
+
+    print(pulse.get_unitary())
+
+    print("finish")
diff --git a/torchquantum/pulse/sesolve/sesolve.py b/torchquantum/pulse/sesolve/sesolve.py
index 85377cf9..e021e945 100644
--- a/torchquantum/pulse/sesolve/sesolve.py
+++ b/torchquantum/pulse/sesolve/sesolve.py
@@ -30,7 +30,6 @@ def sesolve(
     solver.run()
 
     psi_save, exp_save = solver.y_save, solver.exp_save
-
     return psi_save, exp_save
 
 
diff --git a/torchquantum/quantization/__init__.py b/torchquantum/quantization/__init__.py
deleted file mode 100644
index 2c4ede31..00000000
--- a/torchquantum/quantization/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-from .clifford_quantization import CliffordQuantizer
diff --git a/torchquantum/quantization/clifford_quantization.py b/torchquantum/quantization/clifford_quantization.py
index e4f43cbe..3e159d5f 100644
--- a/torchquantum/quantization/clifford_quantization.py
+++ b/torchquantum/quantization/clifford_quantization.py
@@ -6,14 +6,44 @@
 
 
 class QuantizeFunction(torch.autograd.Function):
+    """A custom quantization function for use in the backward pass of CliffordQuantizer.
+
+    Methods:
+        forward(ctx, x): Forward pass of the quantization function.
+
+        backward(ctx, grad_output): Backward pass of the quantization function.
+    """
+    
     @staticmethod
     def forward(ctx: Any, x: torch.Tensor) -> Any:
+        """
+        Forward pass of the quantization function.
+
+        Args:
+            ctx (Any): Context object.
+            x (torch.Tensor): Input tensor.
+
+        Returns:
+            Any: Quantized output tensor.
+        """
+        
         # should be round so that the changes would be small, values close to
         # 2pi should go to 2pi
         return x.round()
 
     @staticmethod
     def backward(ctx: Any, grad_output: Any) -> Any:
+        """
+        Backward pass of the quantization function.
+
+        Args:
+            ctx (Any): Context object.
+            grad_output (Any): Gradient of the output tensor.
+
+        Returns:
+            Any: Gradient of the input tensor.
+        """
+        
         grad_input = grad_output.clone()
         mean, std = grad_input.mean(), grad_input.std()
         return grad_input.clamp_(mean - 3 * std, mean + 3 * std)
@@ -26,6 +56,16 @@ def __init__(self):
     # straight-through estimator
     @staticmethod
     def quantize_sse(params):
+        """
+        Apply straight-through estimator quantization to the given parameters.
+
+        Args:
+            params (torch.Tensor): Input parameters.
+
+        Returns:
+            torch.Tensor: Quantized parameters.
+        """
+        
         param = params[0][0]
         param = param % (2 * np.pi)
         param = np.pi / 2 * QuantizeFunction.apply(param / (np.pi / 2))
diff --git a/torchquantum/util/__init__.py b/torchquantum/util/__init__.py
new file mode 100644
index 00000000..6c43455a
--- /dev/null
+++ b/torchquantum/util/__init__.py
@@ -0,0 +1,26 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .utils import *
+from .vqe_utils import *
diff --git a/torchquantum/util/add_license.sh b/torchquantum/util/add_license.sh
new file mode 100644
index 00000000..9087bdcf
--- /dev/null
+++ b/torchquantum/util/add_license.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+#script to loop through directories to merge files
+
+walk_dir () {    
+    shopt -s nullglob dotglob
+
+    for pathname in "$1"/*; do
+        if [ -d "$pathname" ]; then
+            walk_dir "$pathname"
+        else
+            case "$pathname" in
+                *.py|*.pypypy)
+                    printf '%s\n' "$pathname"
+                    if ! grep -q Copyright $pathname
+                    then
+                        cat license.py $pathname >$pathname.new && mv $pathname.new $pathname
+                    fi
+            esac
+        fi
+    done
+}
+
+DOWNLOADING_DIR="./"
+
+walk_dir "$DOWNLOADING_DIR"
\ No newline at end of file
diff --git a/torchquantum/util/license.py b/torchquantum/util/license.py
new file mode 100644
index 00000000..945fa3a6
--- /dev/null
+++ b/torchquantum/util/license.py
@@ -0,0 +1,24 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
diff --git a/torchquantum/optimization.py b/torchquantum/util/optimization.py
similarity index 86%
rename from torchquantum/optimization.py
rename to torchquantum/util/optimization.py
index 144ae4ca..723487e3 100644
--- a/torchquantum/optimization.py
+++ b/torchquantum/util/optimization.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import numpy as np
 import time
 from scipy.optimize import minimize
diff --git a/torchquantum/util/quantization/__init__.py b/torchquantum/util/quantization/__init__.py
new file mode 100644
index 00000000..a01181ce
--- /dev/null
+++ b/torchquantum/util/quantization/__init__.py
@@ -0,0 +1,25 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .clifford_quantization import CliffordQuantizer
diff --git a/torchquantum/util/quantization/clifford_quantization.py b/torchquantum/util/quantization/clifford_quantization.py
new file mode 100644
index 00000000..402714b7
--- /dev/null
+++ b/torchquantum/util/quantization/clifford_quantization.py
@@ -0,0 +1,57 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torchquantum as tq
+import numpy as np
+
+from typing import Any
+
+
+class QuantizeFunction(torch.autograd.Function):
+    @staticmethod
+    def forward(ctx: Any, x: torch.Tensor) -> Any:
+        # should be round so that the changes would be small, values close to
+        # 2pi should go to 2pi
+        return x.round()
+
+    @staticmethod
+    def backward(ctx: Any, grad_output: Any) -> Any:
+        grad_input = grad_output.clone()
+        mean, std = grad_input.mean(), grad_input.std()
+        return grad_input.clamp_(mean - 3 * std, mean + 3 * std)
+
+
+class CliffordQuantizer(object):
+    def __init__(self):
+        pass
+
+    # straight-through estimator
+    @staticmethod
+    def quantize_sse(params):
+        param = params[0][0]
+        param = param % (2 * np.pi)
+        param = np.pi / 2 * QuantizeFunction.apply(param / (np.pi / 2))
+        params = param.unsqueeze(0).unsqueeze(0)
+        return params
diff --git a/torchquantum/utils.py b/torchquantum/util/utils.py
similarity index 58%
rename from torchquantum/utils.py
rename to torchquantum/util/utils.py
index 2f7f9310..58ef4e03 100644
--- a/torchquantum/utils.py
+++ b/torchquantum/util/utils.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import copy
 from typing import Dict, Iterable, List, TYPE_CHECKING
 
@@ -18,7 +42,7 @@
 
 if TYPE_CHECKING:
     from torchquantum.module import QuantumModule
-    from torchquantum.devices import QuantumDevice
+    from torchquantum.device import QuantumDevice
 else:
     QuantumModule = None
     QuantumDevice = None
@@ -50,6 +74,8 @@
     "tensor_form",
     "matrix_form",
     "dm_to_mixture_of_state",
+    "pauli_string_to_matrix",
+    "parameter_shift_gradient",
 ]
 
 
@@ -71,6 +97,15 @@ def pauli_eigs(n) -> np.ndarray:
 
 
 def diag(x):
+    """
+        Compute the diagonal matrix from a given input tensor.
+
+        Args:
+            x (torch.Tensor): Input tensor.
+
+        Returns:
+            torch.Tensor: Diagonal matrix with the diagonal elements from the input tensor.
+        """
     # input tensor, output tensor with diagonal as the input
     # manual implementation because torch.diag does not support autograd of
     # complex number
@@ -84,6 +119,21 @@ def diag(x):
 
 
 class Timer(object):
+    """
+       Timer class to measure the execution time of a code block.
+
+       Args:
+           device (str): Device to use for timing. Can be "gpu" or "cpu".
+           name (str): Name of the task being measured.
+           times (int): Number of times the task will be executed.
+
+       Example:
+           # Measure the execution time of a code block on the GPU
+           with Timer(device="gpu", name="MyTask", times=100):
+               # Code block to be measured
+               ...
+
+       """
     def __init__(self, device="gpu", name="", times=100):
         self.device = device
         self.name = name
@@ -107,6 +157,21 @@ def __exit__(self, exc_type, exc_value, tb):
 
 
 def get_unitary_loss(model: nn.Module):
+    """
+        Calculate the unitary loss of a model.
+
+        The unitary loss measures the deviation of the trainable unitary matrices
+        in the model from the identity matrix.
+
+        Args:
+            model (nn.Module): The model containing trainable unitary matrices.
+
+        Returns:
+            torch.Tensor: The unitary loss.
+
+        Example:
+            loss = get_unitary_loss(model)
+        """
     loss = 0
     for name, params in model.named_parameters():
         if "TrainableUnitary" in name:
@@ -121,6 +186,22 @@ def get_unitary_loss(model: nn.Module):
 
 
 def legalize_unitary(model: nn.Module):
+    """
+        Legalize the unitary matrices in the model.
+
+        The function modifies the trainable unitary matrices in the model by applying
+        singular value decomposition (SVD) and reassembling the matrices using the
+        reconstructed singular values.
+
+        Args:
+            model (nn.Module): The model containing trainable unitary matrices.
+
+        Returns:
+            None
+
+        Example:
+            legalize_unitary(model)
+        """
     with torch.no_grad():
         for name, params in model.named_parameters():
             if "TrainableUnitary" in name:
@@ -130,6 +211,23 @@ def legalize_unitary(model: nn.Module):
 
 
 def switch_little_big_endian_matrix(mat):
+    """
+        Switches the little-endian and big-endian order of a multi-dimensional matrix.
+
+        The function reshapes the input matrix to a 2D or multi-dimensional matrix with dimensions
+        that are powers of 2. It then switches the order of the dimensions, effectively changing
+        the little-endian order to big-endian, or vice versa. The function can handle both
+        batched and non-batched matrices.
+
+        Args:
+            mat (numpy.ndarray): The input matrix.
+
+        Returns:
+            numpy.ndarray: The matrix with the switched endian order.
+
+        Example:
+            switched_mat = switch_little_big_endian_matrix(mat)
+        """
     if len(mat.shape) % 2 == 1:
         is_batch_matrix = True
         bsz = mat.shape[0]
@@ -152,6 +250,27 @@ def switch_little_big_endian_matrix(mat):
 
 
 def switch_little_big_endian_state(state):
+    """
+       Switches the little-endian and big-endian order of a quantum state vector.
+
+       The function reshapes the input state vector to a 1D or multi-dimensional state vector with
+       dimensions that are powers of 2. It then switches the order of the dimensions, effectively
+       changing the little-endian order to big-endian, or vice versa. The function can handle both
+       batched and non-batched state vectors.
+
+       Args:
+           state (numpy.ndarray): The input state vector.
+
+       Returns:
+           numpy.ndarray: The state vector with the switched endian order.
+
+       Raises:
+           ValueError: If the dimension of the state vector is not 1 or 2.
+
+       Example:
+           switched_state = switch_little_big_endian_state(state)
+       """
+
     if len(state.shape) > 1:
         is_batch_state = True
         bsz = state.shape[0]
@@ -190,6 +309,26 @@ def switch_little_big_endian_state_test():
 
 
 def get_expectations_from_counts(counts, n_wires):
+    """
+       Calculate expectation values from counts.
+
+       This function takes a counts dictionary or a list of counts dictionaries
+       and calculates the expectation values based on the probability of measuring
+       the state '1' on each wire. The expectation values are computed as the
+       flipped difference between the probability of measuring '1' and the probability
+       of measuring '0' on each wire.
+
+       Args:
+           counts (dict or list[dict]): The counts dictionary or a list of counts dictionaries.
+           n_wires (int): The number of wires.
+
+       Returns:
+           numpy.ndarray: The expectation values.
+
+       Example:
+           counts = {'000': 10, '100': 5, '010': 15}
+           expectations = get_expectations_from_counts(counts, 3)
+       """
     exps = []
     if isinstance(counts, dict):
         counts = [counts]
@@ -209,6 +348,30 @@ def get_expectations_from_counts(counts, n_wires):
 
 
 def find_global_phase(mat1, mat2, threshold):
+    """
+        Find a numerical stable global phase between two matrices.
+
+        This function compares the elements of two matrices `mat1` and `mat2`
+        and identifies a numerical stable global phase by finding the first
+        non-zero element pair with absolute values greater than the specified
+        threshold. The global phase is calculated as the ratio of the corresponding
+        elements in `mat2` and `mat1`.
+
+        Args:
+            mat1 (numpy.ndarray): The first matrix.
+            mat2 (numpy.ndarray): The second matrix.
+            threshold (float): The threshold for identifying non-zero elements.
+
+        Returns:
+            float or None: The global phase ratio if a numerical stable phase is found,
+                None otherwise.
+
+        Example:
+            mat1 = np.array([[1+2j, 0+1j], [0-1j, 2+3j]])
+            mat2 = np.array([[2+4j, 0+2j], [0-2j, 4+6j]])
+            threshold = 0.5
+            global_phase = find_global_phase(mat1, mat2, threshold)
+        """
     for i in range(mat1.shape[0]):
         for j in range(mat1.shape[1]):
             # find a numerical stable global phase
@@ -274,6 +437,36 @@ def build_module_op_list(m: QuantumModule, x=None) -> List:
 def build_module_from_op_list(
     op_list: List[Dict], remove_ops=False, thres=None
 ) -> QuantumModule:
+    """
+       Build a quantum module from an operation list.
+
+       This function takes an operation list, which contains dictionaries representing
+       quantum operations, and constructs a quantum module from those operations.
+       The module can optionally remove operations based on certain criteria, such as
+       low parameter values. The removed operations can be counted and logged.
+
+       Args:
+           op_list (List[Dict]): The operation list, where each dictionary represents
+               an operation with keys: "name", "has_params", "trainable", "wires",
+               "n_wires", and "params".
+           remove_ops (bool): Whether to remove operations based on certain criteria.
+               Defaults to False.
+           thres (float): The threshold for removing operations. If a parameter value
+               is smaller in absolute value than this threshold, the corresponding
+               operation is removed. Defaults to None, in which case a threshold of
+               1e-5 is used.
+
+       Returns:
+           QuantumModule: The constructed quantum module.
+
+       Example:
+           op_list = [
+               {"name": "RX", "has_params": True, "trainable": True, "wires": [0], "n_wires": 2, "params": [0.5]},
+               {"name": "CNOT", "has_params": False, "trainable": False, "wires": [0, 1], "n_wires": 2, "params": None},
+               {"name": "RY", "has_params": True, "trainable": True, "wires": [1], "n_wires": 2, "params": [1.2]},
+           ]
+           module = build_module_from_op_list(op_list, remove_ops=True, thres=0.1)
+       """
     logger.info(f"Building module from op_list...")
     thres = 1e-5 if thres is None else thres
     n_removed_ops = 0
@@ -312,9 +505,35 @@ def build_module_from_op_list(
 
 
 def build_module_description_test():
+    """
+        Test function for building module descriptions.
+
+        This function demonstrates the usage of `build_module_op_list` and `build_module_from_op_list`
+        functions to build module descriptions and create quantum modules from those descriptions.
+
+        Example:
+            import pdb
+            from torchquantum.plugins import tq2qiskit
+            from examples.core.models.q_models import QFCModel12
+
+            pdb.set_trace()
+            q_model = QFCModel12({"n_blocks": 4})
+            desc = build_module_op_list(q_model.q_layer)
+            print(desc)
+            q_dev = tq.QuantumDevice(n_wires=4)
+            m = build_module_from_op_list(desc)
+            tq2qiskit(q_dev, m, draw=True)
+
+            desc = build_module_op_list(
+                tq.RandomLayerAllTypes(n_ops=200, wires=[0, 1, 2, 3], qiskit_compatible=True)
+            )
+            print(desc)
+            m1 = build_module_from_op_list(desc)
+            tq2qiskit(q_dev, m1, draw=True)
+        """
     import pdb
 
-    from torchquantum.plugins import tq2qiskit
+    from torchquantum.plugin import tq2qiskit
 
     pdb.set_trace()
     from examples.core.models.q_models import QFCModel12
@@ -410,7 +629,17 @@ def get_v_c_reg_mapping(circ):
 
 
 def get_cared_configs(conf, mode) -> Config:
-    """only preserve cared configs"""
+    """
+        Get the relevant configurations based on the mode.
+
+        Args:
+            conf (Config): The configuration object.
+            mode (str): The mode indicating the desired configuration.
+
+        Returns:
+            Config: The modified configuration object with only the relevant configurations preserved.
+        """
+
     conf = copy.deepcopy(conf)
     ignores = [
         "callbacks",
@@ -476,6 +705,16 @@ def get_cared_configs(conf, mode) -> Config:
 
 
 def get_success_rate(properties, transpiled_circ):
+    """
+        Estimate the success rate of a transpiled quantum circuit.
+
+        Args:
+            properties (list): List of gate error properties.
+            transpiled_circ (QuantumCircuit): The transpiled quantum circuit.
+
+        Returns:
+            float: The estimated success rate.
+        """
     # estimate the success rate according to the error rates of single and
     # two-qubit gates in transpiled circuits
 
@@ -501,6 +740,16 @@ def get_success_rate(properties, transpiled_circ):
 
 
 def get_provider(backend_name, hub=None):
+    """
+        Get the provider object for a specific backend from IBM Quantum.
+
+        Args:
+            backend_name (str): Name of the backend.
+            hub (str): Optional hub name.
+
+        Returns:
+            IBMQProvider: The provider object.
+        """
     # mass-inst-tech-1 or MIT-1
     if backend_name in ["ibmq_casablanca", "ibmq_rome", "ibmq_bogota", "ibmq_jakarta"]:
         if hub == "mass" or hub is None:
@@ -530,13 +779,13 @@ def get_provider(backend_name, hub=None):
             except QiskitError:
                 # logger.warning(f"Cannot use MIT backend, roll back to open")
                 logger.warning(f"Use the open backend")
-                provider = IBMQ.get_provider(hub="ibm-q")
+                provider = IBMQ.get_provider(hub="ibm-q", group="open", project="main")
         elif hub == "mit":
             provider = IBMQ.get_provider(
                 hub="ibm-q-research", group="MIT-1", project="main"
             )
         else:
-            provider = IBMQ.get_provider(hub="ibm-q")
+            provider = IBMQ.get_provider(hub="ibm-q", group="open", project="main")
 
     return provider
 
@@ -551,6 +800,15 @@ def get_provider_hub_group_project(hub="ibm-q", group="open", project="main"):
 
 
 def normalize_statevector(states):
+    """
+       Normalize a statevector to ensure the square magnitude of the statevector sums to 1.
+
+       Args:
+           states (torch.Tensor): The statevector tensor.
+
+       Returns:
+           torch.Tensor: The normalized statevector tensor.
+       """
     # make sure the square magnitude of statevector sum to 1
     # states = states.contiguous()
     original_shape = states.shape
@@ -711,6 +969,23 @@ def dm_to_mixture_of_state(dm: torch.Tensor, atol=1e-10):
 
 
 def partial_trace_test():
+    """
+        Test function for performing partial trace on a quantum device.
+
+        This function demonstrates how to use the `partial_trace` function from `torchquantum.functional`
+        to perform partial trace on a quantum device.
+
+        The function applies Hadamard gate on the first qubit and a CNOT gate between the first and second qubits.
+        Then, it performs partial trace on the first qubit and converts the resulting density matrices into
+        mixtures of states.
+
+        Prints the resulting mixture of states.
+
+        Note: This function assumes that you have already imported the necessary modules and functions.
+
+        Returns:
+            None
+        """
     import torchquantum.functional as tqf
 
     n_wires = 4
@@ -725,8 +1000,89 @@ def partial_trace_test():
 
     print(mixture)
 
+def pauli_string_to_matrix(pauli: str, device=torch.device('cpu')) -> torch.Tensor:
+    mat_dict = {
+        "paulix": torch.tensor([[0, 1], [1, 0]], dtype=C_DTYPE),
+        "pauliy": torch.tensor([[0, -1j], [1j, 0]], dtype=C_DTYPE),
+        "pauliz": torch.tensor([[1, 0], [0, -1]], dtype=C_DTYPE),
+        "i": torch.tensor([[1, 0], [0, 1]], dtype=C_DTYPE),
+    }
+    paulix = mat_dict["paulix"]
+    pauliy = mat_dict["pauliy"]
+    pauliz = mat_dict["pauliz"]
+    iden = mat_dict["i"]
+    pauli_dict = {"X": paulix, "Y": pauliy, "Z": pauliz, "I": iden}
+
+    pauli = pauli.upper()
+
+    matrix = pauli_dict[pauli[0]].to(device)
+
+    for op in pauli[1:]:
+        matrix = torch.kron(matrix, pauli_dict[op].to(device))
+    return matrix
 
 if __name__ == "__main__":
     build_module_description_test()
     switch_little_big_endian_matrix_test()
     switch_little_big_endian_state_test()
+
+
+def parameter_shift_gradient(model, input_data, expectation_operator, shift_rate=np.pi*0.5, shots=1024):
+    ''' 
+    This function calculates the gradient of a parametrized circuit using the parameter shift rule to be fed into 
+    a classical optimizer, its formula is given by 
+    gradient for the ith parameter =( expectation_value(the_ith_parameter + shift_rate)-expectation_value(the_ith_parameter - shift_rate) ) *0.5 
+    Args: 
+        model(tq.QuantumModule): the model that you want to use, which includes the quantum device and the parameters
+        input(torch.tensor): the input data that you are using
+        expectation_operator(str): the observable that you want to calculate the expectation value of, usually the Z operator 
+        (i.e 'ZZZ' for 3 qubits or 3 wires)
+        shift_rate(float , optional): the rate that you would like to shift the parameter with at every iteration, by default pi*0.5
+        shots(int , optional): the number of shots to use per parameter ,(for 10 parameters and 1024 shots = 10240 shots in total)
+        by default = 1024.
+    Returns:
+        torch.tensor : An array of the gradients of all the parameters in the circuit. 
+    '''
+    par_num = []
+    for p in model.parameters():#since the model.parameters() Returns an iterator over module parameters,to get the number of parameter i have to iterate over all of them
+        par_num.append(p)
+    gradient_of_par = torch.zeros(len(par_num))
+                                        
+    def clone_model(model_to_clone):#i have to note:this clone_model function was made with GPT 
+        cloned_model = type(model_to_clone)()  # Create a new instance of the same class
+        cloned_model.load_state_dict(model_to_clone.state_dict())  # Copy the state dictionary
+        return cloned_model
+
+    # Clone the models
+    model_plus_shift  = clone_model(model)
+    model_minus_shift = clone_model(model)
+    state_dict_plus_shift  = model_plus_shift.state_dict()
+    state_dict_minus_shift = model_minus_shift.state_dict()
+    #####################
+
+    for idx, key in enumerate(state_dict_plus_shift):
+        if idx < 2:  # Skip the first two keys because they are not paramters
+            continue
+        state_dict_plus_shift[key]  +=  shift_rate
+        state_dict_minus_shift[key] -=  shift_rate
+        
+        model_plus_shift.load_state_dict(state_dict_plus_shift  )
+        model_minus_shift.load_state_dict(state_dict_minus_shift)
+        
+        model_plus_shift.forward(input_data)
+        model_minus_shift.forward(input_data)
+        
+        state_dict_plus_shift  = model_plus_shift.state_dict()
+        state_dict_minus_shift = model_minus_shift.state_dict()
+                
+        
+        
+        expectation_plus_shift = tq.expval_joint_sampling(model_plus_shift.q_device, observable=expectation_operator, n_shots=shots)
+        expectation_minus_shift = tq.expval_joint_sampling(model_minus_shift.q_device, observable=expectation_operator, n_shots=shots)
+
+
+        state_dict_plus_shift[key]  -=  shift_rate
+        state_dict_minus_shift[key] +=  shift_rate
+        
+        gradient_of_par[idx-2] = (expectation_plus_shift - expectation_minus_shift) * 0.5
+    return gradient_of_par
\ No newline at end of file
diff --git a/torchquantum/vqe_utils.py b/torchquantum/util/vqe_utils.py
similarity index 52%
rename from torchquantum/vqe_utils.py
rename to torchquantum/util/vqe_utils.py
index 5abbc171..9d1f24ca 100644
--- a/torchquantum/vqe_utils.py
+++ b/torchquantum/util/vqe_utils.py
@@ -1,8 +1,42 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import itertools
 import numpy as np
 
 
 def parse_hamiltonian_file(filename: str) -> dict:
+    """
+       Parses a Hamiltonian file and returns the Hamiltonian information as a dictionary.
+
+       Args:
+           filename (str): The name of the Hamiltonian file.
+
+       Returns:
+           dict: A dictionary containing the Hamiltonian information.
+
+       """
     hamil_info = {}
     with open(filename, "r") as rfid:
         lines = rfid.read().split("\n")
@@ -32,6 +66,21 @@ def parse_hamiltonian_file(filename: str) -> dict:
 
 
 def generate_n_hamiltonian(n_wires: int, n_hamil: int, n_lines: int) -> dict:
+    """
+        Generates a random Hamiltonian with a specified number of wires and terms.
+
+        Args:
+            n_wires (int): The number of wires.
+            n_hamil (int): The number of terms in the Hamiltonian.
+            n_lines (int): The desired number of unique Hamiltonians to generate.
+
+        Returns:
+            dict: A dictionary containing the generated Hamiltonian information.
+
+        Raises:
+            AssertionError: If n_hamil is not within the range (0, n_wires].
+
+        """
     assert 0 < n_hamil <= n_wires
 
     hamil_info = {
@@ -63,11 +112,17 @@ def generate_n_hamiltonian(n_wires: int, n_hamil: int, n_lines: int) -> dict:
 
 
 def test_parse_hamiltonian_file():
+    """
+        Test function for parse_hamiltonian_file.
+        """
     file = "../examples/vqe/h2.txt"
     print(parse_hamiltonian_file(file))
 
 
 def test_generate_n_hamiltonian():
+    """
+    Test function for generate_n_hamiltonian.
+    """
     print(generate_n_hamiltonian(n_wires=5, n_hamil=3, n_lines=100))
 
 


Test patch:
diff --git a/examples/qiskit/job_manager_test.py b/examples/qiskit/job_manager_test.py
deleted file mode 100644
index 8b6b2b8c..00000000
--- a/examples/qiskit/job_manager_test.py
+++ /dev/null
@@ -1,37 +0,0 @@
-from qiskit import IBMQ, transpile
-from qiskit.providers.ibmq.managed import IBMQJobManager
-from qiskit.circuit.random import random_circuit
-
-import logging
-
-logging.basicConfig(level=logging.DEBUG)
-
-"""
-WARNING: seems not work on server, reasons unknown yet
-"""
-
-# import pdb
-# pdb.set_trace()
-
-provider = IBMQ.load_account()
-backend = provider.get_backend("ibmqx2")
-
-# Build a thousand circuits.
-circs = []
-for _ in range(1000):
-    circs.append(random_circuit(num_qubits=2, depth=3, measure=True))
-
-# Need to transpile the circuits first.
-circs = transpile(circs, backend=backend)
-
-print("here1")
-
-# Use Job Manager to break the circuits into multiple jobs.
-job_manager = IBMQJobManager()
-job_set_foo = job_manager.run(circs, backend=backend, name="foo")
-
-
-print("here2")
-
-results = job_set_foo.results()
-results.get_counts(5)  # Counts for experiment 5.
diff --git a/test/ControlledU.py b/test/ControlledU.py
deleted file mode 100644
index fc94bc5a..00000000
--- a/test/ControlledU.py
+++ /dev/null
@@ -1,237 +0,0 @@
-# test the controlled unitary function
-
-
-import torchquantum as tq
-import torchquantum.functional as tqf
-
-# import pdb
-# pdb.set_trace()
-
-flag = 8
-
-if flag == 1:
-    state = tq.QuantumState(n_wires=3)
-    print(state)
-
-    state.qubitunitaryfast(wires=0, params=[[0, 1], [1, 0]])
-    state.qubitunitaryfast(wires=2, params=[[0, 1], [1, 0]])
-
-    print(state)
-    state.qubitunitaryfast(
-        wires=[0, 2, 1],
-        params=(
-            [
-                [1, 0, 0, 0, 0, 0, 0, 0],
-                [0, 1, 0, 0, 0, 0, 0, 0],
-                [0, 0, 1, 0, 0, 0, 0, 0],
-                [0, 0, 0, 1, 0, 0, 0, 0],
-                [0, 0, 0, 0, 1, 0, 0, 0],
-                [0, 0, 0, 0, 0, 1, 0, 0],
-                [0, 0, 0, 0, 0, 0, 0, 1],
-                [0, 0, 0, 0, 0, 0, 1, 0],
-            ]
-        ),
-    )
-
-    print(state)
-
-    state = tq.QuantumState(n_wires=3)
-    print(state)
-
-    gate1 = tq.QubitUnitaryFast(init_params=[[0, 1], [1, 0]], n_wires=1, wires=0)
-    gate1(state)
-
-    gate2 = tq.QubitUnitaryFast(init_params=[[0, 1], [1, 0]], n_wires=1, wires=2)
-
-    gate2(state)
-    print(state)
-
-    gate3 = tq.QubitUnitaryFast(
-        init_params=(
-            [
-                [1, 0, 0, 0, 0, 0, 0, 0],
-                [0, 1, 0, 0, 0, 0, 0, 0],
-                [0, 0, 1, 0, 0, 0, 0, 0],
-                [0, 0, 0, 1, 0, 0, 0, 0],
-                [0, 0, 0, 0, 1, 0, 0, 0],
-                [0, 0, 0, 0, 0, 1, 0, 0],
-                [0, 0, 0, 0, 0, 0, 0, 1],
-                [0, 0, 0, 0, 0, 0, 1, 0],
-            ]
-        ),
-        n_wires=3,
-        wires=[0, 2, 1],
-    )
-
-    ## use controlled gate to implement a cnot
-
-    gate3(state)
-    print(state)
-
-if flag == 2:
-    state = tq.QuantumState(n_wires=2)
-    print(state)
-    gate0 = tq.PauliX(n_wires=1, wires=0)
-    gate = tq.QubitUnitaryFast.from_controlled_operation(
-        op=tq.PauliX(), c_wires=0, t_wires=1, trainable=False
-    )
-
-    gate0(state)
-    print(state)
-
-    gate(state)
-    print(state)
-
-if flag == 3:
-    state = tq.QuantumState(n_wires=2)
-    print(state)
-    gate0 = tq.PauliX(n_wires=1, wires=0)
-    gate = tq.QubitUnitaryFast.fromControlledOperation(
-        op=tq.RX(has_params=True, init_params=0.25),
-        c_wires=0,
-        t_wires=1,
-        trainable=False,
-    )
-
-    gate0(state)
-    print(state)
-
-    gate(state)
-    print(state)
-
-
-if flag == 4:
-    state = tq.QuantumState(n_wires=3)
-    print(state)
-    gate0 = tq.PauliX(n_wires=1, wires=0)
-    gate1 = tq.PauliX(n_wires=1, wires=1)
-    gate = tq.QubitUnitaryFast.from_controlled_operation(
-        op=tq.CNOT(), c_wires=0, t_wires=[1, 2], trainable=False
-    )
-
-    gate0(state)
-    print(state)
-
-    gate1(state)
-    print(state)
-
-    gate(state)
-    print(state)
-
-
-if flag == 5:
-    state = tq.QuantumState(n_wires=5)
-    print(state)
-    gate0 = tq.PauliX(n_wires=1, wires=1)
-    gate1 = tq.PauliX(n_wires=1, wires=0)
-    gate2 = tq.PauliX(n_wires=1, wires=4)
-    gate = tq.QubitUnitaryFast.from_controlled_operation(
-        op=tq.CNOT(), c_wires=1, t_wires=[[0, 2], [4, 3]], trainable=False
-    )
-
-    gate0(state)
-    print(state)
-
-    gate1(state)
-    print(state)
-
-    gate2(state)
-    print(state)
-
-    gate(state)
-    print(state)
-
-
-if flag == 6:
-    state = tq.QuantumState(n_wires=5)
-    print(state)
-    gate0 = tq.PauliX(n_wires=1, wires=0)
-    gate1 = tq.PauliX(n_wires=1, wires=1)
-    gate2 = tq.PauliX(n_wires=1, wires=2)
-    gate3 = tq.PauliX(n_wires=1, wires=3)
-
-    # gate2 = tq.PauliX(n_wires=1, wires=4)
-    gate = tq.QubitUnitaryFast.from_controlled_operation(
-        op=tq.Toffoli(), c_wires=[0, 1], t_wires=[2, 3, 4], trainable=False
-    )
-
-    gate0(state)
-    print(state)
-
-    # gate1(state)
-    # print(state)
-
-    gate2(state)
-    print(state)
-
-    gate3(state)
-    print(state)
-
-    gate(state)
-    print(state)
-
-if flag == 7:
-    state = tq.QuantumState(n_wires=9)
-    print(state)
-    gate0 = tq.PauliX(n_wires=1, wires=0)
-    gate1 = tq.PauliX(n_wires=1, wires=1)
-    gate2 = tq.PauliX(n_wires=1, wires=2)
-    gate3 = tq.PauliX(n_wires=1, wires=3)
-    gate4 = tq.PauliX(n_wires=1, wires=4)
-    gate5 = tq.PauliX(n_wires=1, wires=6)
-    gate6 = tq.PauliX(n_wires=1, wires=7)
-
-    # gate2 = tq.PauliX(n_wires=1, wires=4)
-    gate = tq.QubitUnitaryFast.from_controlled_operation(
-        op=tq.Toffoli(),
-        c_wires=[0, 1, 2],
-        t_wires=[[3, 4, 5], [6, 7, 8]],
-        trainable=False,
-    )
-
-    gate0(state)
-    print(state)
-
-    gate1(state)
-    print(state)
-
-    gate2(state)
-    print(state)
-
-    gate3(state)
-    print(state)
-
-    gate4(state)
-    print(state)
-
-    gate5(state)
-    print(state)
-
-    gate6(state)
-    print(state)
-
-    gate(state)
-    print(state)
-
-
-if flag == 8:
-    state = tq.QuantumState(n_wires=3)
-    print(state)
-    gate0 = tq.PauliX(n_wires=1, wires=0)
-    gate1 = tq.PauliX(n_wires=1, wires=1)
-    gate_cx = tq.QubitUnitaryFast.from_controlled_operation(
-        op=tq.PauliX(), c_wires=0, t_wires=1, trainable=False
-    )
-
-    gate_ccx = tq.QubitUnitaryFast.from_controlled_operation(
-        op=gate_cx, c_wires=0, t_wires=[1, 2], trainable=False
-    )
-
-    gate0(state)
-    print(state)
-
-    gate1(state)
-    print(state)
-
-    gate_ccx(state)
-    print(state)
diff --git a/test/__init__.py b/test/__init__.py
index e69de29b..b2b23fa4 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -0,0 +1,26 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from .utils import *
+
diff --git a/test/algorithm/h2.txt b/test/algorithm/h2.txt
new file mode 100644
index 00000000..6b709cb7
--- /dev/null
+++ b/test/algorithm/h2.txt
@@ -0,0 +1,6 @@
+h2 bk 3
+-1.052373245772859 I0 I1
+0.39793742484318045 I0 Z1
+-0.39793742484318045 Z0 I1
+-0.01128010425623538 Z0 Z1
+0.18093119978423156 X0 X1
diff --git a/test/algorithm/test_hamiltonian.py b/test/algorithm/test_hamiltonian.py
new file mode 100644
index 00000000..8f24c007
--- /dev/null
+++ b/test/algorithm/test_hamiltonian.py
@@ -0,0 +1,98 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from torchquantum.algorithm import Hamiltonian
+import numpy as np
+
+def test_hamiltonian():
+    coeffs = [1.0, 1.0]
+    paulis = ["ZZ", "ZX"]
+    hamil = Hamiltonian(coeffs, paulis)
+    assert np.allclose(
+        hamil.get_matrix().cpu().detach().numpy(), 
+        np.array(
+            [[ 1.+0.j,  1.+0.j,  0.+0.j,  0.+0.j],
+            [ 1.+0.j, -1.+0.j,  0.+0.j,  0.+0.j],
+            [ 0.+0.j,  0.+0.j, -1.+0.j, -1.+0.j],
+            [ 0.+0.j,  0.+0.j, -1.+0.j,  1.+0.j]]))
+    
+
+    coeffs = [0.6]
+    paulis = ["XXZ"]
+    hamil = Hamiltonian(coeffs, paulis)
+    assert np.allclose(
+        hamil.get_matrix().cpu().detach().numpy(), 
+        np.array(
+            [[ 0.0000+0.j,  0.0000+0.j,  0.0000+0.j,  0.0000+0.j,  0.0000+0.j,  0.0000+0.j,
+          0.6000+0.j,  0.0000+0.j],
+        [ 0.0000+0.j, -0.0000+0.j,  0.0000+0.j, -0.0000+0.j,  0.0000+0.j, -0.0000+0.j,
+          0.0000+0.j, -0.6000+0.j],
+        [ 0.0000+0.j,  0.0000+0.j,  0.0000+0.j,  0.0000+0.j,  0.6000+0.j,  0.0000+0.j,
+          0.0000+0.j,  0.0000+0.j],
+        [ 0.0000+0.j, -0.0000+0.j,  0.0000+0.j, -0.0000+0.j,  0.0000+0.j, -0.6000+0.j,
+          0.0000+0.j, -0.0000+0.j],
+        [ 0.0000+0.j,  0.0000+0.j,  0.6000+0.j,  0.0000+0.j,  0.0000+0.j,  0.0000+0.j,
+          0.0000+0.j,  0.0000+0.j],
+        [ 0.0000+0.j, -0.0000+0.j,  0.0000+0.j, -0.6000+0.j,  0.0000+0.j, -0.0000+0.j,
+          0.0000+0.j, -0.0000+0.j],
+        [ 0.6000+0.j,  0.0000+0.j,  0.0000+0.j,  0.0000+0.j,  0.0000+0.j,  0.0000+0.j,
+          0.0000+0.j,  0.0000+0.j],
+        [ 0.0000+0.j, -0.6000+0.j,  0.0000+0.j, -0.0000+0.j,  0.0000+0.j, -0.0000+0.j,
+          0.0000+0.j, -0.0000+0.j]]))
+    
+    hamil = Hamiltonian.from_file("test/algorithm/h2.txt")
+
+    assert np.allclose(
+        hamil.matrix.cpu().detach().numpy(), 
+        np.array(
+            [[-1.0636533 +0.j,  0.        +0.j,  0.        +0.j,
+         0.        +0.j,  0.        +0.j,  0.        +0.j,
+         0.1809312 +0.j,  0.        +0.j],
+       [ 0.        +0.j, -1.0636533 +0.j,  0.        +0.j,
+         0.        +0.j,  0.        +0.j,  0.        +0.j,
+         0.        +0.j,  0.1809312 +0.j],
+       [ 0.        +0.j,  0.        +0.j, -1.8369681 +0.j,
+         0.        +0.j,  0.1809312 +0.j,  0.        +0.j,
+         0.        +0.j,  0.        +0.j],
+       [ 0.        +0.j,  0.        +0.j,  0.        +0.j,
+        -1.8369681 +0.j,  0.        +0.j,  0.1809312 +0.j,
+         0.        +0.j,  0.        +0.j],
+       [ 0.        +0.j,  0.        +0.j,  0.1809312 +0.j,
+         0.        +0.j, -0.24521835+0.j,  0.        +0.j,
+         0.        +0.j,  0.        +0.j],
+       [ 0.        +0.j,  0.        +0.j,  0.        +0.j,
+         0.1809312 +0.j,  0.        +0.j, -0.24521835+0.j,
+         0.        +0.j,  0.        +0.j],
+       [ 0.1809312 +0.j,  0.        +0.j,  0.        +0.j,
+         0.        +0.j,  0.        +0.j,  0.        +0.j,
+        -1.0636533 +0.j,  0.        +0.j],
+       [ 0.        +0.j,  0.1809312 +0.j,  0.        +0.j,
+         0.        +0.j,  0.        +0.j,  0.        +0.j,
+         0.        +0.j, -1.0636533 +0.j]]))
+    print("hamiltonian test passed!")
+
+if __name__ == '__main__':
+    import pdb
+    pdb.set_trace()
+    test_hamiltonian()
diff --git a/test/device/test_init.py b/test/device/test_init.py
new file mode 100644
index 00000000..9b5fd878
--- /dev/null
+++ b/test/device/test_init.py
@@ -0,0 +1,43 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torchquantum as tq
+import torch
+from torchquantum.macro import C_DTYPE, C_DTYPE_NUMPY
+
+import numpy as np
+
+
+def test_state_init():
+    qdev = tq.QuantumDevice(n_wires=2, bsz=2)
+    np.testing.assert_array_equal(
+        qdev.get_states_1d().cpu().data.numpy(),
+        np.array([[1, 0, 0, 0], [1, 0, 0, 0]], dtype=C_DTYPE_NUMPY),
+    )
+
+    qdev = tq.QuantumDevice(n_wires=2, bsz=1)
+    np.testing.assert_array_equal(
+        qdev.get_states_1d().cpu().data.numpy(),
+        np.array([[1, 0, 0, 0]], dtype=C_DTYPE_NUMPY),
+    )
diff --git a/test/devices/test_init.py b/test/devices/test_init.py
deleted file mode 100644
index c662e9a7..00000000
--- a/test/devices/test_init.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import torchquantum as tq
-import torch
-from torchquantum.macro import C_DTYPE, C_DTYPE_NUMPY
-
-import numpy as np
-
-
-def test_state_init():
-    qdev = tq.QuantumDevice(n_wires=2, bsz=2)
-    np.testing.assert_array_equal(
-        qdev.get_states_1d().cpu().data.numpy(),
-        np.array([[1, 0, 0, 0], [1, 0, 0, 0]], dtype=C_DTYPE_NUMPY),
-    )
-
-    qdev = tq.QuantumDevice(n_wires=2, bsz=1)
-    np.testing.assert_array_equal(
-        qdev.get_states_1d().cpu().data.numpy(),
-        np.array([[1, 0, 0, 0]], dtype=C_DTYPE_NUMPY),
-    )
diff --git a/test/functional/test_controlled_unitary.py b/test/functional/test_controlled_unitary.py
new file mode 100644
index 00000000..0236d165
--- /dev/null
+++ b/test/functional/test_controlled_unitary.py
@@ -0,0 +1,189 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torchquantum as tq
+from test.utils import check_all_close
+import numpy as np
+
+def test_controlled_unitary():
+    state = tq.QuantumDevice(n_wires=2)
+    # print(state)
+    # gate0 = tq.PauliX(n_wires=1, wires=0)
+    # gate = tq.QubitUnitaryFast.from_controlled_operation(
+    #     op=tq.PauliX(), c_wires=0, t_wires=1, trainable=False
+    # )
+
+    state.paulix(0)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j]]))
+    # print(state)
+    state.controlled_unitary(params=tq.PauliX().matrix, c_wires=0, t_wires=1)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+    # gate(state)
+    # print(state)
+
+    ############################
+    state = tq.QuantumDevice(n_wires=2)
+
+    # gate0 = tq.PauliX(n_wires=1, wires=0)
+    # gate = tq.QubitUnitaryFast.from_controlled_operation(
+    #     op=tq.RX(has_params=True, init_params=0.25),
+    #     c_wires=0,
+    #     t_wires=1,
+    #     trainable=False,
+    # )
+
+    state.paulix(0)
+    rx_gate = tq.RX(has_params=True, init_params=0.25)
+    state.controlled_unitary(params=rx_gate.matrix, c_wires=0, t_wires=1)
+    check_all_close(state.get_states_1d(), np.array([[0.       +0.j        , 0.       +0.j        ,
+        0.9921977+0.j        , 0.       -0.12467473j]]))
+
+
+    ############################
+    gate0 = tq.PauliX(n_wires=1, wires=0)
+    gate1 = tq.PauliX(n_wires=1, wires=1)
+    gate = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.CNOT(), c_wires=0, t_wires=[1, 2], trainable=False
+    )
+    state = tq.QuantumDevice(n_wires=3)
+    state.paulix(0)
+    state.paulix(1)
+    state.controlled_unitary(params=tq.CNOT().matrix, c_wires=0, t_wires=[1, 2])
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+    ############################
+    state = tq.QuantumDevice(n_wires=5)
+    state.paulix(0)
+    state.paulix(1)
+    state.paulix(4)
+    state.controlled_unitary(params=tq.CNOT().matrix, c_wires=1, t_wires=[[0, 2], [4, 3]])
+    check_all_close(state.get_states_1d(),
+                    np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+    
+    ############################
+    state = tq.QuantumDevice(n_wires=5)
+    state.paulix(0)
+    state.paulix(1)
+    state.paulix(2)
+    state.paulix(3)
+    state.controlled_unitary(params=tq.Toffoli().matrix, c_wires=[0, 1], t_wires=[2, 3, 4])
+    check_all_close(state.get_states_1d(),
+                    np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+    
+    ############################
+    state = tq.QuantumDevice(n_wires=9)
+    state.paulix(0)
+    state.paulix(1)
+    state.paulix(2)
+    state.paulix(3)
+    state.paulix(4)
+    state.paulix(6)
+    state.paulix(7)
+
+    state.controlled_unitary(params=tq.Toffoli().matrix, c_wires=[0, 1, 2], t_wires=[[3, 4, 5], [6, 7, 8]])
+    check_all_close(state.get_states_1d(),
+                    np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+    ###############################
+    gate_cx = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.PauliX(), c_wires=0, t_wires=1, trainable=False
+    )
+    state = tq.QuantumDevice(n_wires=3)
+    state.paulix(0)
+    state.paulix(1)
+    state.controlled_unitary(params=gate_cx.matrix, c_wires=0, t_wires=[1, 2])
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+if __name__ == "__main__":
+    test_controlled_unitary()
diff --git a/test/functional/test_func_mat_exp.py b/test/functional/test_func_mat_exp.py
new file mode 100644
index 00000000..1e0cbdb3
--- /dev/null
+++ b/test/functional/test_func_mat_exp.py
@@ -0,0 +1,64 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import torch
+import torchquantum as tq
+import numpy as np
+
+
+def test_func_mat_exp():
+    qdev = tq.QuantumDevice(n_wires=3)
+    qdev.reset_states(bsz=1)
+
+    qdev.matrix_exp(wires=[0], params=torch.tensor([[1., 2.], [3., 4.+1.j]]))
+
+    assert np.allclose(
+        qdev.get_states_1d().cpu().detach().numpy(), 
+        np.array(
+        [[44.2796+23.9129j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j,
+         85.5304+68.1896j,  0.0000+0.0000j,  0.0000+0.0000j,  0.0000+0.0000j]])
+         )
+    
+    qdev = tq.QuantumDevice(n_wires=3)
+    qdev.reset_states(bsz=2)
+
+    qdev.matrix_exp(wires=[0, 2], params=torch.tensor([[1., 2., 2, 1], 
+                                                       [3., 4.+1.j,  2, 1], 
+                                                       [1., 2., 2, 1], 
+                                                       [3., 4.+1.j,  2, 1]])
+                                                       )  # type: ignore
+    # print(qdev.get_states_1d().cpu().detach().numpy())
+
+    assert np.allclose(
+        qdev.get_states_1d().cpu().detach().numpy(), 
+        np.array(
+        [[483.20386+254.27155j, 747.27014+521.95013j,   0.+0.j, 0.+0.j, 482.2038+254.27151j, 747.27014+521.95013j, 0.+0.j,        0.+0.j],
+         [483.20386+254.27155j, 747.27014+521.95013j,   0.+0.j, 0.+0.j, 482.2038+254.27151j, 747.27014+521.95013j, 0.+0.j,        0.+0.j]]
+    ))
+
+if __name__ == '__main__':
+    import pdb
+    pdb.set_trace()
+
+    test_func_mat_exp()
\ No newline at end of file
diff --git a/test/hadamard_grad/test_hadamard_grad.py b/test/hadamard_grad/test_hadamard_grad.py
new file mode 100644
index 00000000..c6d3d7cd
--- /dev/null
+++ b/test/hadamard_grad/test_hadamard_grad.py
@@ -0,0 +1,39 @@
+import numpy as np
+from examples.hadamard_grad.circ import Circ1, Circ2, Circ3
+from examples.hadamard_grad.hadamard_grad import hadamard_grad
+
+def test_hadamard_grad():
+    '''
+    We assume the circuits have unique and ordered parameters for now.
+    This simplifies the hadamard_grad function so that it only needs to return a list ordered as op_history
+    '''
+
+    example_circuits = [
+        Circ1,
+        Circ2,
+        Circ3
+    ]
+
+    for Circ in example_circuits:
+        circ = Circ()
+        expval, qdev = circ()
+
+        # hadamard grad
+        op_history = qdev.op_history
+        n_wires = qdev.n_wires
+        observable = 'ZZZZ'
+        hadamard_grad_result = hadamard_grad(op_history, n_wires, observable)
+        hadamard_grad_result = [gradient for gradient in hadamard_grad_result if gradient != None]
+
+        # backpropagation
+        expval.backward()
+
+        # comparison
+        for i, (name, param) in enumerate(circ.named_parameters()):
+            assert np.isclose(hadamard_grad_result[i], param.grad, atol=0.001), "The gradient for {} is incorrect.".format(name)
+
+    print("tq.hadamard_grad test passed")
+
+if __name__ == "__main__":
+
+    test_hadamard_grad()
\ No newline at end of file
diff --git a/test/measurement/test_eval_observable.py b/test/measurement/test_eval_observable.py
index 063882c9..2968fe64 100644
--- a/test/measurement/test_eval_observable.py
+++ b/test/measurement/test_eval_observable.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 from qiskit import QuantumCircuit
 import numpy as np
 import random
@@ -6,8 +30,8 @@
 import torchquantum as tq
 
 from torchquantum.measurement import expval_joint_analytical, expval_joint_sampling
-from torchquantum.plugins import op_history2qiskit
-from torchquantum.utils import switch_little_big_endian_state
+from torchquantum.plugin import op_history2qiskit
+from torchquantum.util import switch_little_big_endian_state
 
 import torch
 
diff --git a/test/measurement/test_expval_joint_sampling_grouping.py b/test/measurement/test_expval_joint_sampling_grouping.py
index a513d95f..3d430c23 100644
--- a/test/measurement/test_expval_joint_sampling_grouping.py
+++ b/test/measurement/test_expval_joint_sampling_grouping.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 from torchquantum.measurement import expval_joint_analytical, expval_joint_sampling_grouping
 
diff --git a/test/measurement/test_find_observable_groups.py b/test/measurement/test_find_observable_groups.py
index 95710d10..c3e81348 100644
--- a/test/measurement/test_find_observable_groups.py
+++ b/test/measurement/test_find_observable_groups.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 from torchquantum.measurement import find_observable_groups
 from random import shuffle
 
diff --git a/test/measurement/test_measure.py b/test/measurement/test_measure.py
index 50d1743d..5873d3c7 100644
--- a/test/measurement/test_measure.py
+++ b/test/measurement/test_measure.py
@@ -1,6 +1,30 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import torchquantum as tq
 
-from torchquantum.plugins import op_history2qiskit
+from torchquantum.plugin import op_history2qiskit
 from qiskit import Aer, transpile
 import numpy as np
 
diff --git a/test/operator/test_ControlledU.py b/test/operator/test_ControlledU.py
new file mode 100644
index 00000000..1348862d
--- /dev/null
+++ b/test/operator/test_ControlledU.py
@@ -0,0 +1,322 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+# test the controlled unitary function
+
+
+import torchquantum as tq
+import torchquantum.functional as tqf
+from test.utils import check_all_close
+# import pdb
+# pdb.set_trace()
+import numpy as np
+
+
+flag = 4
+
+def test_ContorlledU():
+    state = tq.QuantumDevice(n_wires=3)
+    # print(state)
+
+    state.qubitunitaryfast(wires=0, params=[[0, 1], [1, 0]])
+    state.qubitunitaryfast(wires=2, params=[[0, 1], [1, 0]])
+
+    # print(state)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j]]))
+    state.qubitunitaryfast(
+        wires=[0, 2, 1],
+        params=(
+            [
+                [1, 0, 0, 0, 0, 0, 0, 0],
+                [0, 1, 0, 0, 0, 0, 0, 0],
+                [0, 0, 1, 0, 0, 0, 0, 0],
+                [0, 0, 0, 1, 0, 0, 0, 0],
+                [0, 0, 0, 0, 1, 0, 0, 0],
+                [0, 0, 0, 0, 0, 1, 0, 0],
+                [0, 0, 0, 0, 0, 0, 0, 1],
+                [0, 0, 0, 0, 0, 0, 1, 0],
+            ]
+        ),
+    )
+
+    # print(state)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+    state = tq.QuantumDevice(n_wires=3)
+    # print(state)
+
+
+    gate1 = tq.QubitUnitaryFast(init_params=[[0, 1], [1, 0]], n_wires=1, wires=0)
+    gate1(state)
+
+    gate2 = tq.QubitUnitaryFast(init_params=[[0, 1], [1, 0]], n_wires=1, wires=2)
+
+    gate2(state)
+    # print(state)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j, 0.+0.j]]))
+
+    gate3 = tq.QubitUnitaryFast(
+        init_params=(
+            [
+                [1, 0, 0, 0, 0, 0, 0, 0],
+                [0, 1, 0, 0, 0, 0, 0, 0],
+                [0, 0, 1, 0, 0, 0, 0, 0],
+                [0, 0, 0, 1, 0, 0, 0, 0],
+                [0, 0, 0, 0, 1, 0, 0, 0],
+                [0, 0, 0, 0, 0, 1, 0, 0],
+                [0, 0, 0, 0, 0, 0, 0, 1],
+                [0, 0, 0, 0, 0, 0, 1, 0],
+            ]
+        ),
+        n_wires=3,
+        wires=[0, 2, 1],
+    )
+
+    ## use controlled gate to implement a cnot
+
+    gate3(state)
+    # print(state)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+
+    ############################
+    state = tq.QuantumDevice(n_wires=2)
+
+    gate0 = tq.PauliX(n_wires=1, wires=0)
+    gate = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.PauliX(), c_wires=0, t_wires=1, trainable=False
+    )
+
+    gate0(state)
+    # print(state)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 1.+0.j, 0.+0.j]]))
+
+    gate(state)
+    # print(state)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+
+    ############################
+    state = tq.QuantumDevice(n_wires=2)
+
+    gate0 = tq.PauliX(n_wires=1, wires=0)
+    gate = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.RX(has_params=True, init_params=0.25),
+        c_wires=0,
+        t_wires=1,
+        trainable=False,
+    )
+
+    gate0(state)
+
+    gate(state)
+    check_all_close(state.get_states_1d(), np.array([[0.       +0.j        , 0.       +0.j        ,
+        0.9921977+0.j        , 0.       -0.12467473j]]))
+    # print(state)
+
+
+    ############################
+    state = tq.QuantumDevice(n_wires=3)
+    gate0 = tq.PauliX(n_wires=1, wires=0)
+    gate1 = tq.PauliX(n_wires=1, wires=1)
+    gate = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.CNOT(), c_wires=0, t_wires=[1, 2], trainable=False
+    )
+
+    gate0(state)
+    # print(state)
+
+    gate1(state)
+    # print(state)
+
+    gate(state)
+    # print(state)
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+
+    ############################
+
+    state = tq.QuantumDevice(n_wires=5)
+
+    gate0 = tq.PauliX(n_wires=1, wires=1)
+    gate1 = tq.PauliX(n_wires=1, wires=0)
+    gate2 = tq.PauliX(n_wires=1, wires=4)
+    gate = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.CNOT(), c_wires=1, t_wires=[[0, 2], [4, 3]], trainable=False
+    )
+
+    gate0(state)
+    gate1(state)
+    gate2(state)
+
+    gate(state)
+    check_all_close(state.get_states_1d(),
+                    np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+    ############################
+    state = tq.QuantumDevice(n_wires=5)
+
+    gate0 = tq.PauliX(n_wires=1, wires=0)
+    gate1 = tq.PauliX(n_wires=1, wires=1)
+    gate2 = tq.PauliX(n_wires=1, wires=2)
+    gate3 = tq.PauliX(n_wires=1, wires=3)
+
+    # gate2 = tq.PauliX(n_wires=1, wires=4)
+    gate = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.Toffoli(), c_wires=[0, 1], t_wires=[2, 3, 4], trainable=False
+    )
+
+    gate0(state)
+    gate1(state)
+    gate2(state)
+    gate3(state)
+
+    gate(state)
+    check_all_close(state.get_states_1d(),
+                    np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+    ############################
+    state = tq.QuantumDevice(n_wires=9)
+
+    gate0 = tq.PauliX(n_wires=1, wires=0)
+    gate1 = tq.PauliX(n_wires=1, wires=1)
+    gate2 = tq.PauliX(n_wires=1, wires=2)
+    gate3 = tq.PauliX(n_wires=1, wires=3)
+    gate4 = tq.PauliX(n_wires=1, wires=4)
+    gate5 = tq.PauliX(n_wires=1, wires=6)
+    gate6 = tq.PauliX(n_wires=1, wires=7)
+
+    # gate2 = tq.PauliX(n_wires=1, wires=4)
+    gate = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.Toffoli(),
+        c_wires=[0, 1, 2],
+        t_wires=[[3, 4, 5], [6, 7, 8]],
+        trainable=False,
+    )
+
+    gate0(state)
+    gate1(state)
+    gate2(state)
+    gate3(state)
+    gate4(state)
+    gate5(state)
+    gate6(state)
+
+    gate(state)
+    check_all_close(state.get_states_1d(),
+                    np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j,
+        0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+    ##############################
+    state = tq.QuantumDevice(n_wires=3)
+
+    gate0 = tq.PauliX(n_wires=1, wires=0)
+    gate1 = tq.PauliX(n_wires=1, wires=1)
+    gate_cx = tq.QubitUnitaryFast.from_controlled_operation(
+        op=tq.PauliX(), c_wires=0, t_wires=1, trainable=False
+    )
+
+    gate_ccx = tq.QubitUnitaryFast.from_controlled_operation(
+        op=gate_cx, c_wires=0, t_wires=[1, 2], trainable=False
+    )
+
+    gate0(state)
+    gate1(state)
+
+    gate_ccx(state)
+
+    check_all_close(state.get_states_1d(), np.array([[0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j]]))
+
+
+
+if __name__ == "__main__":
+    test_ContorlledU()
diff --git a/test/operators/test_op.py b/test/operator/test_op.py
similarity index 63%
rename from test/operators/test_op.py
rename to test/operator/test_op.py
index c0fd2eac..519bb2ef 100644
--- a/test/operators/test_op.py
+++ b/test/operator/test_op.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 # test the torchquantum.functional against the IBM Qiskit
 import argparse
 import pdb
@@ -5,10 +29,13 @@
 import numpy as np
 
 from torchpack.utils.logging import logger
-from torchquantum.utils import switch_little_big_endian_matrix
+from torchquantum.util import switch_little_big_endian_matrix
 from tqdm import tqdm
 
 import qiskit.circuit.library.standard_gates as qiskit_gate
+import qiskit.circuit.library as qiskit_library
+from qiskit.quantum_info import Operator
+
 
 RND_TIMES = 100
 
@@ -45,10 +72,31 @@
     {"qiskit": qiskit_gate.U1Gate, "tq": tq.U1},
     {"qiskit": qiskit_gate.U2Gate, "tq": tq.U2},
     {"qiskit": qiskit_gate.U3Gate, "tq": tq.U3},
+    {"qiskit": qiskit_gate.CUGate, "tq": tq.CU},
     {"qiskit": qiskit_gate.CU1Gate, "tq": tq.CU1},
     # {'qiskit': qiskit_gate.?, 'tq': tq.CU2},
     {"qiskit": qiskit_gate.CU3Gate, "tq": tq.CU3},
     {"qiskit": qiskit_gate.ECRGate, "tq": tq.ECR},
+    # {"qiskit": qiskit_library.QFT, "tq": tq.QFT},
+    {"qiskit": qiskit_gate.SdgGate, "tq": tq.SDG},
+    {"qiskit": qiskit_gate.TdgGate, "tq": tq.TDG},
+    {"qiskit": qiskit_gate.SXdgGate, "tq": tq.SXDG},
+    {"qiskit": qiskit_gate.CHGate, "tq": tq.CH},
+    {"qiskit": qiskit_gate.CCZGate, "tq": tq.CCZ},
+    {"qiskit": qiskit_gate.iSwapGate, "tq": tq.ISWAP},
+    {"qiskit": qiskit_gate.CSGate, "tq": tq.CS},
+    {"qiskit": qiskit_gate.CSdgGate, "tq": tq.CSDG},
+    {"qiskit": qiskit_gate.CSXGate, "tq": tq.CSX},
+    {"qiskit": qiskit_gate.DCXGate, "tq": tq.DCX},
+    {"qiskit": qiskit_gate.XXMinusYYGate, "tq": tq.XXMINYY},
+    {"qiskit": qiskit_gate.XXPlusYYGate, "tq": tq.XXPLUSYY},
+    {"qiskit": qiskit_gate.C3XGate, "tq": tq.C3X},
+    {"qiskit": qiskit_gate.RGate, "tq": tq.R},
+    {"qiskit": qiskit_gate.C4XGate, "tq": tq.C4X},
+    {"qiskit": qiskit_gate.RCCXGate, "tq": tq.RCCX},
+    {"qiskit": qiskit_gate.RC3XGate, "tq": tq.RC3X},
+    {"qiskit": qiskit_gate.GlobalPhaseGate, "tq": tq.GlobalPhase},
+    {"qiskit": qiskit_gate.C3SXGate, "tq": tq.C3SX},
 ]
 
 import os
@@ -79,6 +127,8 @@ def test_op():
                 if pair["tq"]().name == "SHadamard":
                     """Square root of Hadamard is RY(pi/4)"""
                     qiskit_matrix = qiskit_gate.RYGate(theta=np.pi / 4).to_matrix()
+                elif pair["tq"]().name == "C3SX":
+                    qiskit_matrix = Operator(pair["qiskit"]())
                 else:
                     qiskit_matrix = pair["qiskit"]().to_matrix()
                 tq_matrix = pair["tq"].matrix.numpy()
diff --git a/test/operator/test_op_hamil_exp.py b/test/operator/test_op_hamil_exp.py
new file mode 100644
index 00000000..de65fa06
--- /dev/null
+++ b/test/operator/test_op_hamil_exp.py
@@ -0,0 +1,72 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from torchquantum.operator import OpHamilExp
+from torchquantum.algorithm import Hamiltonian
+import numpy as np
+from test.utils import check_all_close
+from torchquantum.device import QuantumDevice
+
+def test_op_hamil_exp():
+    hamil = Hamiltonian(coeffs=[1.0, 0.5], paulis=['ZZ', 'XX'])
+    op = OpHamilExp(hamil=hamil,
+                    trainable=True,
+                    theta=0.45)
+    
+    print(op.matrix)
+    print(op.exponent_matrix)
+
+    check_all_close(
+        op.matrix,
+        np.array([[ 0.9686-0.2217j,  0.0000+0.0000j,  0.0000+0.0000j, -0.0250-0.1094j],
+        [ 0.0000+0.0000j,  0.9686+0.2217j,  0.0250-0.1094j,  0.0000+0.0000j],
+        [ 0.0000+0.0000j,  0.0250-0.1094j,  0.9686+0.2217j,  0.0000+0.0000j],
+        [-0.0250-0.1094j,  0.0000+0.0000j,  0.0000+0.0000j,  0.9686-0.2217j]])
+    )
+
+    check_all_close(
+        op.exponent_matrix,
+        np.array([[0.-0.2250j, 0.+0.0000j, 0.+0.0000j, 0.-0.1125j],
+        [0.+0.0000j, 0.+0.2250j, 0.-0.1125j, 0.+0.0000j],
+        [0.+0.0000j, 0.-0.1125j, 0.+0.2250j, 0.+0.0000j],
+        [0.-0.1125j, 0.+0.0000j, 0.+0.0000j, 0.-0.2250j]])
+    )
+
+    qdev = QuantumDevice(n_wires=2)
+    qdev.reset_states(bsz=2)
+
+    op(qdev, wires=[1, 0])
+
+    print(qdev.get_states_1d().cpu().detach().numpy())
+
+    check_all_close(
+        qdev.get_states_1d().cpu().detach().numpy(),
+        np.array([[ 0.9686322 -0.22169423j , 0.        +0.j        ,  0.        +0.j, -0.02504631-0.1094314j ],
+                  [ 0.9686322 -0.22169423j , 0.        +0.j        ,  0.        +0.j, -0.02504631-0.1094314j ]])
+    )
+
+if __name__ == '__main__':
+    # import pdb
+    # pdb.set_trace()
+    test_op_hamil_exp()
diff --git a/test/plugin/test_qiskit2tq_op_history.py b/test/plugin/test_qiskit2tq_op_history.py
new file mode 100644
index 00000000..48f2c82e
--- /dev/null
+++ b/test/plugin/test_qiskit2tq_op_history.py
@@ -0,0 +1,48 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+from torchquantum.plugin import qiskit2tq_op_history
+import torchquantum as tq
+from qiskit.circuit.random import random_circuit
+from qiskit import QuantumCircuit
+
+
+def test_qiskit2tp_op_history():
+    circ = QuantumCircuit(3, 3)
+    circ.h(0)
+    circ.rx(0.1, 1)
+    circ.cx(0, 1)
+    circ.cx(1, 2)
+    circ.u(0.1, 0.2, 0.3, 0)
+    print(circ)
+    ops = qiskit2tq_op_history(circ)
+    qmodule = tq.QuantumModule.from_op_history(ops)
+    print(qmodule.Operator_list)
+
+
+
+if __name__ == '__main__':
+    import pdb
+    pdb.set_trace()
+    test_qiskit2tp_op_history()
diff --git a/test/plugins/test_qiskit_plugins.py b/test/plugin/test_qiskit_plugins.py
similarity index 57%
rename from test/plugins/test_qiskit_plugins.py
rename to test/plugin/test_qiskit_plugins.py
index a675ec94..4e4fdb28 100644
--- a/test/plugins/test_qiskit_plugins.py
+++ b/test/plugin/test_qiskit_plugins.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 from qiskit import QuantumCircuit
 import numpy as np
 import random
@@ -5,8 +29,8 @@
 
 import torchquantum as tq
 
-from torchquantum.plugins import op_history2qiskit, QiskitProcessor
-from torchquantum.utils import switch_little_big_endian_state
+from torchquantum.plugin import op_history2qiskit, QiskitProcessor
+from torchquantum.util import switch_little_big_endian_state
 
 import torch
 
@@ -34,7 +58,7 @@ def test_expval_observable():
         random_layer(qdev)
         qiskit_circ = op_history2qiskit(qdev.n_wires, qdev.op_history)
 
-        expval_qiskit_processor = processor.process_circs_get_joint_expval([qiskit_circ], "".join(obs))
+        expval_qiskit_processor = processor.process_circs_get_joint_expval([qiskit_circ], "".join(obs), parallel=False)
 
         operator = pauli_str_op_dict[obs[0]]
         for ob in obs[1:]:
@@ -56,4 +80,6 @@ def test_expval_observable():
 
 
 if __name__ == '__main__':
+    import pdb
+    pdb.set_trace()
     test_expval_observable()
diff --git a/test/plugins/test_qiskit2tq_op_history.py b/test/plugins/test_qiskit2tq_op_history.py
deleted file mode 100644
index 64faa0ad..00000000
--- a/test/plugins/test_qiskit2tq_op_history.py
+++ /dev/null
@@ -1,24 +0,0 @@
-from torchquantum.plugins import qiskit2tq_op_history
-import torchquantum as tq
-from qiskit.circuit.random import random_circuit
-from qiskit import QuantumCircuit
-
-
-def test_qiskit2tp_op_history():
-    circ = QuantumCircuit(3, 3)
-    circ.h(0)
-    circ.rx(0.1, 1)
-    circ.cx(0, 1)
-    circ.cx(1, 2)
-    circ.u(0.1, 0.2, 0.3, 0)
-    print(circ)
-    ops = qiskit2tq_op_history(circ)
-    qmodule = tq.QuantumModule.from_op_history(ops)
-    print(qmodule.Operator_list)
-
-
-
-if __name__ == '__main__':
-    import pdb
-    pdb.set_trace()
-    test_qiskit2tp_op_history()
diff --git a/test/qiskit_plugin_test.py b/test/qiskit_plugin_test.py
index 6b0a9972..d8b7e94b 100644
--- a/test/qiskit_plugin_test.py
+++ b/test/qiskit_plugin_test.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import argparse
 import pdb
 import torch
@@ -6,14 +30,14 @@
 
 from qiskit import Aer, execute
 from torchpack.utils.logging import logger
-from torchquantum.utils import (
+from torchquantum.util import (
     switch_little_big_endian_matrix,
     switch_little_big_endian_state,
     get_expectations_from_counts,
     find_global_phase,
 )
 from test.static_mode_test import QLayer as AllRandomLayer
-from torchquantum.plugins import tq2qiskit
+from torchquantum.plugin import tq2qiskit
 from torchquantum.macro import F_DTYPE
 
 
diff --git a/test/random_layer_test.py b/test/random_layer_test.py
index 59270f8e..db9f91d2 100644
--- a/test/random_layer_test.py
+++ b/test/random_layer_test.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 from torchquantum import tq
 
 
diff --git a/test/static_mode_test.py b/test/static_mode_test.py
index 43057f1c..6c2a3428 100644
--- a/test/static_mode_test.py
+++ b/test/static_mode_test.py
@@ -1,3 +1,27 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
 import argparse
 import pdb
 import torch
@@ -5,10 +29,10 @@
 import numpy as np
 
 from torchpack.utils.logging import logger
-from torchquantum.operators import op_name_dict
+from torchquantum.operator.operators import op_name_dict
 from torchquantum.functional import func_name_dict
 from torchquantum.macro import F_DTYPE
-from torchquantum.plugins.qiskit_macros import (
+from torchquantum.plugin.qiskit import (
     QISKIT_INCOMPATIBLE_FUNC_NAMES,
     QISKIT_INCOMPATIBLE_OPS,
 )
diff --git a/test/utils.py b/test/utils.py
new file mode 100644
index 00000000..a1af86e5
--- /dev/null
+++ b/test/utils.py
@@ -0,0 +1,36 @@
+"""
+MIT License
+
+Copyright (c) 2020-present TorchQuantum Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+
+import numpy as np
+import torch
+
+def check_all_close(a, b, rtol=1e-5, atol=1e-4):
+    """Check that all elements of a and b are close."""
+    if isinstance(a, torch.Tensor):
+        a = a.detach().cpu().numpy()
+    if isinstance(b, torch.Tensor):
+        b = b.detach().cpu().numpy()
+    assert a.shape == b.shape
+    assert np.allclose(a, b, rtol=rtol, atol=atol)