1+ import numpy as np
2+ import stim
3+ from bitarray import bitarray
4+
5+
6+ def fixed_weight_tableau (n_qubits , n_meas , weight , XYZ = False ):
7+
8+ """Generates a tableau in dict form, with n_meas pure Z stabilizers of given weight
9+ and pure X destabilizes of arbitrary weight
10+ This can be given as the argument "tableau" to the Stabilizer constructor
11+
12+ If XYZ is False, will yield random Z stabilizers only"""
13+
14+ if n_meas >= n_qubits :
15+ raise Exception (
16+ "n_meas should be strictly less than n_qubits"
17+ )
18+ if weight >= n_qubits :
19+ raise Exception (
20+ "Your Paulis are overweight :( weight should be strictly less than n_qubits"
21+ )
22+
23+ # bistring generation in lexicographic order: https://stackoverflow.com/a/58072652
24+ def kbits (n , k ):
25+ limit = 1 << n
26+ val = (1 << k )- 1
27+ while val < limit :
28+ yield "{0:0{1}b}" .format (val ,n )
29+ minbit = val & - val #rightmost 1 bit
30+ fillbit = (val + minbit )& ~ val #rightmost 0 to the left of that bit
31+ val = val + minbit | (fillbit // (minbit << 1 ))- 1
32+
33+ Stabz = np .zeros (n_qubits )
34+
35+ for val in kbits (n_qubits , weight ):
36+ valarray = bitarray (val ).tolist ()
37+ Stabz = np .vstack ((Stabz , valarray ))
38+
39+ Stabz = np .delete (Stabz , 0 , 0 )
40+ Stabz = Stabz .astype (int )
41+
42+ rng = np .random .default_rng ()
43+ rng .shuffle (Stabz )
44+
45+
46+ if XYZ :
47+
48+ def commutes_with_all (Stabxyz_list , newstab ):
49+
50+ commutes = True
51+ index = 0
52+
53+ while commutes & index < len (Stabxyz_list ):
54+ anticommutations = (newstab != Stabxyz_list [index ]) #TODO: just use qiskit lmao
55+ commutes = not sum (anticommutations ) % 2
56+ index += 1
57+
58+ return commutes
59+
60+ PauliArray = rng .choice (range (1 ,4 ), n_qubits )
61+ mask = rng .choice (Stabz )
62+ Stabxyz = np .array ([PauliArray * mask ])
63+
64+ while np .linalg .matrix_rank (Stabxyz ) < n_meas : # TODO : check linear independence using qiskit symplectic notation or stim
65+ current_rank = np .linalg .rank (Stabxyz )
66+ while np .linalg .matrix_rank (Stabxyz ) == current_rank :
67+ PauliArray = rng .choice (range (1 ,4 ), n_qubits )
68+ mask = rng .choice (Stabz )
69+ Stabxyz = np .vstack (Stabxyz , PauliArray * mask )
70+
71+ #TODO : randomize signs BUT careful that they're not contradictory like +Z and -Z
72+
73+
74+
75+ stimStabz = (3 * Stabz ).tolist () # In Stim, 0=I, 1=X, 2=Y, 3=Z
76+ stimStabz = [stim .PauliString (stab ) for stab in stimStabz ]
77+
78+ tableau = stim .Tableau .from_stabilizers (stimStabz , allow_redundant = True , allow_underconstrained = True )
79+
80+ # Translate to Qiskit and choose n_meas stabilizers
81+ stabilizer = [str (tableau .z_output (i )).replace ('_' ,'I' ) for i in range (n_meas )]
82+ destabilizer = [str (tableau .x_output (i )).replace ('_' ,'I' ) for i in range (n_meas )]
83+ tableau_dict = {"stabilizer" : stabilizer , "destabilizer" : destabilizer }
84+
85+ return (tableau_dict )
86+
87+ # print(fixed_weight_tableau(10,5,5,XYZ=True))
0 commit comments