Skip to content

Commit ec3ffb5

Browse files
add inputs and state for stabilizercircuit
1 parent 33cd4c8 commit ec3ffb5

File tree

4 files changed

+72
-1
lines changed

4 files changed

+72
-1
lines changed

docs/source/api/stabilizercircuit.rst

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
tensorcircuit.stabilizercircuit
2+
================================================================================
3+
.. automodule:: tensorcircuit.stabilizercircuit
4+
:members:
5+
:undoc-members:
6+
:show-inheritance:
7+
:inherited-members:

tensorcircuit/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434

3535
try:
3636
from .stabilizercircuit import StabilizerCircuit
37+
38+
CliffordCircuit = StabilizerCircuit
3739
except ModuleNotFoundError:
3840
pass
3941

tensorcircuit/stabilizercircuit.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,24 @@ class StabilizerCircuit(AbstractCircuit):
3131
"sd": "S_DAG",
3232
}
3333

34-
def __init__(self, nqubits: int) -> None:
34+
def __init__(self, nqubits: int, inputs: Tensor = None) -> None:
35+
"""
36+
``StabilizerCircuit`` class based on stim package
37+
38+
:param nqubits: Number of qubits
39+
:type nqubits: int
40+
:param inputs: initial state by stabilizers, defaults to None
41+
:type inputs: Tensor, optional
42+
"""
3543
self._nqubits = nqubits
3644
self._stim_circuit = stim.Circuit()
3745
self._qir: List[Dict[str, Any]] = []
3846
self.is_dm = False
3947
self.inputs = None
4048
self._extra_qir: List[Dict[str, Any]] = []
4149
self.current_sim = stim.TableauSimulator()
50+
if inputs:
51+
self.current_sim.set_state_from_stabilizers(inputs)
4252

4353
def apply_general_gate(
4454
self,
@@ -89,6 +99,14 @@ def apply_general_gate(
8999

90100
apply = apply_general_gate
91101

102+
def state(self) -> Tensor:
103+
"""
104+
Return the wavefunction of the circuit.
105+
Note that the state can have smaller qubit count if no gate is applied on later qubits
106+
"""
107+
tab = self.current_tableau()
108+
return tab.to_state_vector(endian="big")
109+
92110
def random_gate(self, *index: int, recorded: bool = False) -> None:
93111
"""
94112
Apply a random Clifford gate to the circuit.
@@ -296,6 +314,20 @@ def mid_measurement(self, index: int, keep: int = 0) -> Tensor:
296314
post_select = mid_measurement
297315
post_selection = mid_measurement
298316

317+
def depolarizing(self, *index: int, p: float) -> None:
318+
"""
319+
Apply depolarizing noise to a qubit.
320+
321+
:param index: Index of the qubit to apply noise to
322+
:type index: int
323+
:param p: Noise parameter (probability of depolarizing)
324+
:type p: float
325+
"""
326+
self._stim_circuit.append_from_stim_program_text(
327+
f"DEPOLARIZE1({p}) {' '.join(map(str, index))}"
328+
)
329+
self.current_sim.depolarize1(*index, p=p)
330+
299331
def current_simulator(self) -> stim.TableauSimulator:
300332
"""
301333
Return the current simulator of the circuit.

tests/test_stabilizer.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
sys.path.insert(0, modulepath)
1111
import tensorcircuit as tc
1212

13+
# Skip all tests if stim is not installed
14+
stim = pytest.importorskip("stim")
15+
1316

1417
def test_basic_gates():
1518
c = tc.StabilizerCircuit(2)
@@ -155,3 +158,30 @@ def test_random_gates():
155158
c.random_gate(1, 2)
156159
print(c.entanglement_entropy(list(range(2))))
157160
print(len(c.current_circuit()))
161+
162+
163+
def test_circuit_state():
164+
c = tc.StabilizerCircuit(2)
165+
c.h(1)
166+
c1 = tc.Circuit(2)
167+
c1.h(1)
168+
np.testing.assert_allclose(c.state(), c1.state(), atol=1e-5)
169+
170+
171+
def test_circuit_inputs():
172+
c = tc.StabilizerCircuit(2, inputs=[stim.PauliString("XX"), stim.PauliString("ZZ")])
173+
c.cnot(0, 1)
174+
c.h(0)
175+
np.testing.assert_allclose(c.expectation_ps(z=[0]), 1, atol=1e-6)
176+
np.testing.assert_allclose(c.expectation_ps(z=[1]), 1, atol=1e-6)
177+
178+
179+
def test_depolarize():
180+
r = []
181+
for _ in range(20):
182+
c = tc.StabilizerCircuit(2)
183+
c.h(0)
184+
c.depolarizing(0, 1, p=0.2)
185+
c.h(0)
186+
r.append(c.expectation_ps(z=[0]))
187+
assert 10 < np.sum(r) < 20

0 commit comments

Comments
 (0)