Skip to content

Commit 5bf8919

Browse files
authored
Add internal evolve methods by Clifford gates (#15813)
* add _evolve_sx, _evolve_sxdg, _evolve_dcx, _evolve_iswap * add tests for _append_circuit method * rewrite _evolve_dcx * rewrite _evolve_iswap * simplify _evolve_iswap phase calc * update test * unify tests * enhance test of a random clifford circuit to include qargs * enhance test for a random clifford circuit to include h method * test only evolve and not internal methods * simlify tests
1 parent 858acb4 commit 5bf8919

2 files changed

Lines changed: 65 additions & 0 deletions

File tree

qiskit/quantum_info/operators/symplectic/base_pauli.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,22 @@ def _evolve_sdg(base_pauli, qubit):
636636
return base_pauli
637637

638638

639+
def _evolve_sx(base_pauli, qubit):
640+
"""Update P -> SX.P.SXdg"""
641+
z = base_pauli._z[:, qubit]
642+
base_pauli._x[:, qubit] ^= z
643+
base_pauli._phase -= z.T.astype(base_pauli._phase.dtype)
644+
return base_pauli
645+
646+
647+
def _evolve_sxdg(base_pauli, qubit):
648+
"""Update P -> SXdg.P.SX"""
649+
z = base_pauli._z[:, qubit]
650+
base_pauli._x[:, qubit] ^= z
651+
base_pauli._phase += z.T.astype(base_pauli._phase.dtype)
652+
return base_pauli
653+
654+
639655
def _evolve_i(base_pauli, qubit):
640656
"""Update P -> P"""
641657
return base_pauli
@@ -690,6 +706,15 @@ def _evolve_cy(base_pauli, qctrl, qtrgt):
690706
return base_pauli
691707

692708

709+
def _evolve_dcx(base_pauli, qctrl, qtrgt):
710+
"""Update P -> DCX.P.DCXdg"""
711+
base_pauli._x[:, qtrgt] ^= base_pauli._x[:, qctrl]
712+
base_pauli._z[:, qctrl] ^= base_pauli._z[:, qtrgt]
713+
base_pauli._x[:, qctrl] ^= base_pauli._x[:, qtrgt]
714+
base_pauli._z[:, qtrgt] ^= base_pauli._z[:, qctrl]
715+
return base_pauli
716+
717+
693718
def _evolve_swap(base_pauli, q1, q2):
694719
"""Update P -> SWAP.P.SWAP"""
695720
x1 = base_pauli._x[:, q1].copy()
@@ -701,6 +726,22 @@ def _evolve_swap(base_pauli, q1, q2):
701726
return base_pauli
702727

703728

729+
def _evolve_iswap(base_pauli, q1, q2):
730+
"""Update P -> iSWAP.P.iSWAP"""
731+
x1 = base_pauli._x[:, q1].copy()
732+
z1 = base_pauli._z[:, q1].copy()
733+
x2 = base_pauli._x[:, q2].copy()
734+
z2 = base_pauli._z[:, q2].copy()
735+
736+
base_pauli._x[:, q1] = x2
737+
base_pauli._x[:, q2] = x1
738+
base_pauli._z[:, q1] = x1 ^ x2 ^ z2
739+
base_pauli._z[:, q2] = x1 ^ x2 ^ z1
740+
741+
base_pauli._phase += np.logical_xor(x1, x2).T.astype(base_pauli._phase.dtype)
742+
return base_pauli
743+
744+
704745
def _evolve_ecr(base_pauli, q1, q2):
705746
"""Update P -> ECR.P.ECR"""
706747
base_pauli = _evolve_s(base_pauli, q1)
@@ -740,13 +781,17 @@ def _count_y(x, z, dtype=None):
740781
"s": _evolve_s,
741782
"sdg": _evolve_sdg,
742783
"sinv": _evolve_sdg,
784+
"sx": _evolve_sx,
785+
"sxdg": _evolve_sxdg,
743786
}
744787
_basis_2q = {
745788
"cx": _evolve_cx,
746789
"cz": _evolve_cz,
747790
"cy": _evolve_cy,
748791
"swap": _evolve_swap,
792+
"iswap": _evolve_iswap,
749793
"ecr": _evolve_ecr,
794+
"dcx": _evolve_dcx,
750795
}
751796

752797
# Non-Clifford gates

test/python/quantum_info/operators/symplectic/test_pauli.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
from qiskit import QuantumCircuit
2626
from qiskit.circuit import Qubit
27+
from qiskit.circuit.random import random_clifford_circuit
2728
from qiskit.circuit.library import (
2829
CXGate,
2930
CYGate,
@@ -36,6 +37,7 @@
3637
SGate,
3738
SwapGate,
3839
iSwapGate,
40+
DCXGate,
3941
XGate,
4042
YGate,
4143
ZGate,
@@ -449,6 +451,7 @@ def test_evolve_clifford1(self, gate, label):
449451
SwapGate(),
450452
iSwapGate(),
451453
ECRGate(),
454+
DCXGate(),
452455
CPhaseGate(theta=np.pi),
453456
CRXGate(theta=np.pi),
454457
CRYGate(theta=np.pi),
@@ -489,11 +492,15 @@ def test_evolve_clifford2(self, gate, label):
489492
HGate(),
490493
SGate(),
491494
SdgGate(),
495+
SXGate(),
496+
SXdgGate(),
492497
CXGate(),
493498
CYGate(),
494499
CZGate(),
495500
SwapGate(),
501+
iSwapGate(),
496502
ECRGate(),
503+
DCXGate(),
497504
),
498505
[int, np.int8, np.uint8, np.int16, np.uint16, np.int32, np.uint32, np.int64, np.uint64],
499506
)
@@ -523,6 +530,19 @@ def test_evolve_clifford_qargs(self):
523530
self.assertEqual(value, value_h)
524531
self.assertEqual(value_inv, value_s)
525532

533+
def test_evolve_clifford_circuit_qargs(self):
534+
"""Test evolve method for random Clifford circuit"""
535+
qargs = [2, 4, 1, 0]
536+
qc = random_clifford_circuit(4, 100, seed=123)
537+
op = Operator(qc)
538+
pauli = random_pauli(5, seed=5678)
539+
target_s = Operator(pauli).compose(op, qargs=qargs).dot(op.adjoint(), qargs=qargs)
540+
target_h = Operator(pauli).compose(op.adjoint(), qargs=qargs).dot(op, qargs=qargs)
541+
value_evolve_s = Operator(pauli.evolve(qc, frame="s", qargs=qargs))
542+
value_evolve_h = Operator(pauli.evolve(qc, frame="h", qargs=qargs))
543+
self.assertEqual(value_evolve_s, target_s)
544+
self.assertEqual(value_evolve_h, target_h)
545+
526546
@data("s", "h")
527547
def test_evolve_with_misleading_name(self, frame):
528548
"""Test evolve by circuit contents, not by name (fixed bug)."""

0 commit comments

Comments
 (0)