Skip to content

Commit f538629

Browse files
author
Zhuoyang Ye
committed
[Test]Single qubit density matrix test compared with qiskit.
1 parent 12b67b8 commit f538629

File tree

5 files changed

+175
-1
lines changed

5 files changed

+175
-1
lines changed

test/density/test_density_op.py

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
"""
2+
MIT License
3+
4+
Copyright (c) 2020-present TorchQuantum Authors
5+
6+
Permission is hereby granted, free of charge, to any person obtaining a copy
7+
of this software and associated documentation files (the "Software"), to deal
8+
in the Software without restriction, including without limitation the rights
9+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
copies of the Software, and to permit persons to whom the Software is
11+
furnished to do so, subject to the following conditions:
12+
13+
The above copyright notice and this permission notice shall be included in all
14+
copies or substantial portions of the Software.
15+
16+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
SOFTWARE.
23+
"""
24+
25+
# test the torchquantum.functional against the IBM Qiskit
26+
import argparse
27+
import pdb
28+
import torchquantum as tq
29+
import numpy as np
30+
31+
import qiskit.circuit.library.standard_gates as qiskit_gate
32+
from qiskit.quantum_info import DensityMatrix as qiskitDensity
33+
34+
from unittest import TestCase
35+
import qiskit.circuit.library as qiskit_library
36+
from qiskit.quantum_info import Operator
37+
38+
RND_TIMES = 100
39+
40+
single_gate_list = [
41+
{"qiskit": qiskit_gate.HGate, "tq": tq.h, "name": "Hadamard"},
42+
{"qiskit": qiskit_gate.XGate, "tq": tq.x, "name": "x"},
43+
{"qiskit": qiskit_gate.YGate, "tq": tq.y, "name": "y"},
44+
{"qiskit": qiskit_gate.ZGate, "tq": tq.z, "name": "z"},
45+
{"qiskit": qiskit_gate.SGate, "tq": tq.S, "name": "S"},
46+
{"qiskit": qiskit_gate.TGate, "tq": tq.T, "name": "T"},
47+
{"qiskit": qiskit_gate.SXGate, "tq": tq.SX, "name": "SX"},
48+
{"qiskit": qiskit_gate.SdgGate, "tq": tq.SDG, "name": "SDG"},
49+
{"qiskit": qiskit_gate.TdgGate, "tq": tq.TDG, "name": "TDG"}
50+
]
51+
52+
pair_list = [
53+
{"qiskit": qiskit_gate.HGate, "tq": tq.Hadamard},
54+
{"qiskit": None, "tq": tq.SHadamard},
55+
{"qiskit": qiskit_gate.XGate, "tq": tq.PauliX},
56+
{"qiskit": qiskit_gate.YGate, "tq": tq.PauliY},
57+
{"qiskit": qiskit_gate.ZGate, "tq": tq.PauliZ},
58+
{"qiskit": qiskit_gate.SGate, "tq": tq.S},
59+
{"qiskit": qiskit_gate.TGate, "tq": tq.T},
60+
{"qiskit": qiskit_gate.SXGate, "tq": tq.SX},
61+
{"qiskit": qiskit_gate.CXGate, "tq": tq.CNOT},
62+
{"qiskit": qiskit_gate.CYGate, "tq": tq.CY},
63+
{"qiskit": qiskit_gate.CZGate, "tq": tq.CZ},
64+
{"qiskit": qiskit_gate.RXGate, "tq": tq.RX},
65+
{"qiskit": qiskit_gate.RYGate, "tq": tq.RY},
66+
{"qiskit": qiskit_gate.RZGate, "tq": tq.RZ},
67+
{"qiskit": qiskit_gate.RXXGate, "tq": tq.RXX},
68+
{"qiskit": qiskit_gate.RYYGate, "tq": tq.RYY},
69+
{"qiskit": qiskit_gate.RZZGate, "tq": tq.RZZ},
70+
{"qiskit": qiskit_gate.RZXGate, "tq": tq.RZX},
71+
{"qiskit": qiskit_gate.SwapGate, "tq": tq.SWAP},
72+
# {'qiskit': qiskit_gate.?, 'tq': tq.SSWAP},
73+
{"qiskit": qiskit_gate.CSwapGate, "tq": tq.CSWAP},
74+
{"qiskit": qiskit_gate.CCXGate, "tq": tq.Toffoli},
75+
{"qiskit": qiskit_gate.PhaseGate, "tq": tq.PhaseShift},
76+
# {'qiskit': qiskit_gate.?, 'tq': tq.Rot},
77+
# {'qiskit': qiskit_gate.?, 'tq': tq.MultiRZ},
78+
{"qiskit": qiskit_gate.CRXGate, "tq": tq.CRX},
79+
{"qiskit": qiskit_gate.CRYGate, "tq": tq.CRY},
80+
{"qiskit": qiskit_gate.CRZGate, "tq": tq.CRZ},
81+
# {'qiskit': qiskit_gate.?, 'tq': tq.CRot},
82+
{"qiskit": qiskit_gate.UGate, "tq": tq.U},
83+
{"qiskit": qiskit_gate.U1Gate, "tq": tq.U1},
84+
{"qiskit": qiskit_gate.U2Gate, "tq": tq.U2},
85+
{"qiskit": qiskit_gate.U3Gate, "tq": tq.U3},
86+
{"qiskit": qiskit_gate.CUGate, "tq": tq.CU},
87+
{"qiskit": qiskit_gate.CU1Gate, "tq": tq.CU1},
88+
# {'qiskit': qiskit_gate.?, 'tq': tq.CU2},
89+
{"qiskit": qiskit_gate.CU3Gate, "tq": tq.CU3},
90+
{"qiskit": qiskit_gate.ECRGate, "tq": tq.ECR},
91+
# {"qiskit": qiskit_library.QFT, "tq": tq.QFT},
92+
{"qiskit": qiskit_gate.SdgGate, "tq": tq.SDG},
93+
{"qiskit": qiskit_gate.TdgGate, "tq": tq.TDG},
94+
{"qiskit": qiskit_gate.SXdgGate, "tq": tq.SXDG},
95+
{"qiskit": qiskit_gate.CHGate, "tq": tq.CH},
96+
{"qiskit": qiskit_gate.CCZGate, "tq": tq.CCZ},
97+
{"qiskit": qiskit_gate.iSwapGate, "tq": tq.ISWAP},
98+
{"qiskit": qiskit_gate.CSGate, "tq": tq.CS},
99+
{"qiskit": qiskit_gate.CSdgGate, "tq": tq.CSDG},
100+
{"qiskit": qiskit_gate.CSXGate, "tq": tq.CSX},
101+
{"qiskit": qiskit_gate.DCXGate, "tq": tq.DCX},
102+
{"qiskit": qiskit_gate.XXMinusYYGate, "tq": tq.XXMINYY},
103+
{"qiskit": qiskit_gate.XXPlusYYGate, "tq": tq.XXPLUSYY},
104+
{"qiskit": qiskit_gate.C3XGate, "tq": tq.C3X},
105+
{"qiskit": qiskit_gate.RGate, "tq": tq.R},
106+
{"qiskit": qiskit_gate.C4XGate, "tq": tq.C4X},
107+
{"qiskit": qiskit_gate.RCCXGate, "tq": tq.RCCX},
108+
{"qiskit": qiskit_gate.RC3XGate, "tq": tq.RC3X},
109+
{"qiskit": qiskit_gate.GlobalPhaseGate, "tq": tq.GlobalPhase},
110+
{"qiskit": qiskit_gate.C3SXGate, "tq": tq.C3SX},
111+
]
112+
113+
114+
def density_is_close(mat1: np.ndarray, mat2: np.ndarray):
115+
assert mat1.shape == mat2.shape
116+
return np.allclose(mat1, mat2)
117+
118+
119+
("Geeks : %2d, Portal : %5.2f" % (1, 05.333))
120+
121+
122+
class single_qubit(TestCase):
123+
def compare_single_gate(self, gate_pair, qubit_num):
124+
passed = True
125+
for index in range(0, qubit_num):
126+
qdev = tq.NoiseDevice(n_wires=qubit_num, bsz=1, device="cpu", record_op=True)
127+
gate_pair['tq'](qdev, [index])
128+
mat1 = np.array(qdev.get_2d_matrix(0))
129+
rho_qiskit = qiskitDensity.from_label('0' * qubit_num)
130+
rho_qiskit = rho_qiskit.evolve(gate_pair['qiskit'](), [qubit_num - 1 - index])
131+
mat2 = np.array(rho_qiskit.to_operator())
132+
if density_is_close(mat1, mat2):
133+
print("Test passed for %s gate on qubit %d when qubit_number is %d!" % (
134+
gate_pair['name'], index, qubit_num))
135+
else:
136+
passed = False
137+
print("Test failed for %s gaet on qubit %d when qubit_number is %d!" % (
138+
gate_pair['name'], index, qubit_num))
139+
return passed
140+
141+
def test_single_gates(self):
142+
for i in range(0, len(single_gate_list)):
143+
self.assertTrue(self.compare_single_gate(single_gate_list[i], 5))

test/density/test_density_trace.py

Whitespace-only changes.

torchquantum/density/density_mat.py

+6
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ def print_2d(self, index):
126126
_matrix = torch.reshape(self._matrix[index], [2 ** self.n_wires] * 2)
127127
print(_matrix)
128128

129+
130+
def get_2d_matrix(self, index):
131+
_matrix = torch.reshape(self._matrix[index], [2 ** self.n_wires] * 2)
132+
return _matrix
133+
134+
129135
def trace(self, index):
130136
"""Calculate and return the trace of the density matrix at the given index.
131137

torchquantum/device/noisedevices.py

+26
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,32 @@ def __init__(
7373
self.record_op = record_op
7474
self.op_history = []
7575

76+
77+
def print_2d(self, index):
78+
"""Print the matrix value at the given index.
79+
80+
This method prints the matrix value of `matrix[index]`. It reshapes the value into a 2D matrix
81+
using the `torch.reshape` function and then prints it.
82+
83+
Args:
84+
index (int): The index of the matrix value to print.
85+
86+
Examples:
87+
>>> device = QuantumDevice(n_wires=2)
88+
>>> device.matrix = torch.tensor([[1, 0, 0, 0], [0, 0, 1, 0], [0, 1, 0, 0], [0, 0, 0, 1]])
89+
>>> device.print_2d(1)
90+
tensor([[0, 0],
91+
[0, 1]])
92+
93+
"""
94+
95+
_matrix = torch.reshape(self.densities[index], [2 ** self.n_wires] * 2)
96+
print(_matrix)
97+
98+
def get_2d_matrix(self, index):
99+
_matrix = torch.reshape(self.densities[index], [2 ** self.n_wires] * 2)
100+
return _matrix
101+
76102
@property
77103
def name(self):
78104
"""Return the name of the device."""

torchquantum/functional/gate_wrapper.py

-1
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,6 @@ def gate_wrapper(
433433
assert np.log2(matrix.shape[-1]) == len(wires)
434434
if q_device.device_name=="noisedevice":
435435
density = q_device.densities
436-
print(density.shape)
437436
if method == "einsum":
438437
return
439438
elif method == "bmm":

0 commit comments

Comments
 (0)