I'd like to understand how the signs in the tableau are calculated and if there's a way to force them to be +. Here's an example that shows what I see : (this is an encoder for $[[8,3,3]]$ code)
import stim
def circuit_to_tableau(circuit: stim.Circuit) -> stim.Tableau:
s=stim.TableauSimulator()
s.do_circuit(circuit)
return s.current_inverse_tableau() ** -1
circuit=stim.Circuit('''
CX 5 4
CX 6 5
CX 7 6
H 0
CX 0 4
CX 0 5
CX 0 6
CZ 0 6
H 1
CZ 1 0
CX 1 4
CX 1 5
CZ 1 5
CX 1 7
H 2
CZ 2 0
CX 2 4
CZ 2 5
CX 2 6
CX 2 7
CZ 2 7
H 3
CZ 3 0
CZ 3 1
CX 3 5
CX 3 6
CZ 3 6
CX 3 7
CZ 3 7
MPP Y0*Z2*Z3*X4*X5*Y6
MPP Z0*Y1*Z3*X4*Y5*X7
MPP Z0*Y2*X4*Z5*X6*Y7
MPP Z0*Z1*X3*X5*Y6*Y7
MPP Z0*Z1*Z2*Z3*Z4*Z5*Z6*Z7
''')
sampler=circuit.compile_sampler()
print(sampler.sample(shots=8))
tableau=circuit_to_tableau(circuit)
print(repr(tableau))
running it gives this result :
[[False False False True False]
[False False False True False]
[False False False True False]
[False False False True False]
[False False False True False]
[False False False True False]
[False False False True False]
[False False False True False]]
stim.Tableau.from_conjugated_generators(
xs=[
stim.PauliString("+Z_______"),
stim.PauliString("+_Z______"),
stim.PauliString("+__Z_____"),
stim.PauliString("+___Z____"),
stim.PauliString("+____X___"),
stim.PauliString("+_ZZ_XX__"),
stim.PauliString("+ZZZZ_XX_"),
stim.PauliString("+Z_Z___XX"),
],
zs=[
stim.PauliString("+Y_ZZXXY_"),
stim.PauliString("+ZY_ZXY_X"),
stim.PauliString("+Z_Y_XZXY"),
stim.PauliString("-ZZ_X_XYY"),
stim.PauliString("+ZZZZZZZZ"),
stim.PauliString("+___Z_ZZZ"),
stim.PauliString("+ZZ____ZZ"),
stim.PauliString("+_ZZZ___Z"),
],
)
Why did the fourth z stabilizer pick up a minus sign? these are all stabilizers, destabilizers, and logical for the code and everything works the same with + for all of them.
(PS. Let me know if there's a better place to post Stim specific questions...I have several about syntax ... and I don't want to clutter things here)
Here's another approach to get the encoding circuit using the routines described in a previous post how to go from matrix to tableau to circuit in qiskit or stim
matrix=[
[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,1,0,0,0,0,0,0,0,0,0,0,0],
[0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0],
[0,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0],
[0,0,0,0,1,0,0,1,0,0,1,1,0,0,0,0],
[1,0,0,0,1,1,1,0,1,0,1,1,0,0,1,0],
[0,1,0,0,1,1,0,1,1,1,0,1,0,1,0,0],
[0,0,1,0,1,0,1,1,1,0,1,0,0,1,0,1],
[0,0,0,1,0,1,1,1,1,1,0,0,0,0,1,1],
[0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1],
[0,0,0,0,0,0,0,0,1,1,0,1,0,1,0,0],
[0,0,0,0,0,0,0,0,1,0,1,1,0,0,1,0],
[0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,1]]
tableau = bit_matrix_to_tableau(matrix)
print(repr(tableau))
circuit1 = tableau_to_circuit_simple(tableau)
circuit2=stim.Circuit('''
MPP Y0*Z2*Z3*X4*X5*Y6
MPP Z0*Y1*Z3*X4*Y5*X7
MPP Z0*Y2*X4*Z5*X6*Y7
MPP Z0*Z1*X3*X5*Y6*Y7
MPP Z0*Z1*Z2*Z3*Z4*Z5*Z6*Z7
''')
circuit=circuit1+circuit2
sampler=circuit.compile_sampler()
print(sampler.sample(shots=8))
tableau=circuit_to_tableau(circuit)
print(repr(tableau))
This gives a + for all stabilizers when the tableau is generated from a matrix and even when you go matrix -> tableau -> circuit -> tableau
stim.Tableau.from_conjugated_generators(
xs=[
stim.PauliString("+Z_______"),
stim.PauliString("+_Z______"),
stim.PauliString("+__Z_____"),
stim.PauliString("+___Z____"),
stim.PauliString("+____X___"),
stim.PauliString("+_ZZ_XX__"),
stim.PauliString("+Z__ZX_X_"),
stim.PauliString("+__ZZX__X"),
],
zs=[
stim.PauliString("+Y_ZZXXY_"),
stim.PauliString("+ZY_ZXY_X"),
stim.PauliString("+Z_Y_XZXY"),
stim.PauliString("+ZZ_X_XYY"),
stim.PauliString("+ZZZZZZZZ"),
stim.PauliString("+ZZ_Z_Z__"),
stim.PauliString("+Z_ZZ__Z_"),
stim.PauliString("+_ZZZ___Z"),
],
)
[[False False False False False]
[False False False False False]
[False False False False False]
[False False False False False]
[False False False False False]
[False False False False False]
[False False False False False]
[False False False False False]]
stim.Tableau.from_conjugated_generators(
xs=[
stim.PauliString("+Z_______"),
stim.PauliString("+_Z______"),
stim.PauliString("+__Z_____"),
stim.PauliString("+___Z____"),
stim.PauliString("+____X___"),
stim.PauliString("+_ZZ_XX__"),
stim.PauliString("+Z__ZX_X_"),
stim.PauliString("+__ZZX__X"),
],
zs=[
stim.PauliString("+Y_ZZXXY_"),
stim.PauliString("+ZY_ZXY_X"),
stim.PauliString("+Z_Y_XZXY"),
stim.PauliString("+ZZ_X_XYY"),
stim.PauliString("+ZZZZZZZZ"),
stim.PauliString("+ZZ_Z_Z__"),
stim.PauliString("+Z_ZZ__Z_"),
stim.PauliString("+_ZZZ___Z"),
],
)
circuit_to_tableau
method you used is only valid if you stick to unitary operations. Your circuit contains measurements, so it is not describable using a tableau. Tableaus only represent Cliffords, not measurements or other dissipative operations. If you happen to be measuring stabilizers so the measurements are deterministic then it's fine... but beware. $\endgroup$circuit1 + circuit2
concatenates their instructions into a new circuit. $\endgroup$