The famous 3 - qubit Greenberger, Horne and Zeilinger state: $|GHZ_{3} \rangle = \frac{1}{\sqrt{2}}[|000\rangle + |111\rangle]$.

A stabiliser for $|GHZ_{3} \rangle$ is the 3 - tensor product X Pauli operators: $S_{1} = \sigma_{X} \otimes \sigma_{X} \otimes \sigma_{X}$.

Then, $S_{1} |GHZ_{3}\rangle = |GHZ_{3}\rangle$.

The question is how does one determine all possible stabiliser for $|GHZ_{3} \rangle$?

  • 1
    $\begingroup$ Do you mean operators whos +1 eigenstate is GHZ state? If thats the case then there are infinite such operators. But if you want only tensor product of paulis, then you can just iterate over all 4^3, doing matrix vector multiplication and checking if thats correct. $\endgroup$
    – FDGod
    Sep 21, 2023 at 9:40
  • $\begingroup$ @FDGod Only tensor products of Pauli operators. I think I know what you're saying but just for clarity, are you able to provide a reasonably verbose answer? I promise to accept it. $\endgroup$
    – Physkid
    Sep 21, 2023 at 9:43
  • 1
    $\begingroup$ I’ll try to write a detailed answer — with “tricks/intution” to figure out if a state is invariant upto a global phase for which pauli operators — sometime tomorrow if no one answers in the meantime. Its 3 AM and I should sleep now lol. $\endgroup$
    – FDGod
    Sep 21, 2023 at 10:09
  • $\begingroup$ @FDGod Thank you for the kindness. Sleep is important. $\endgroup$
    – Physkid
    Sep 21, 2023 at 10:17

2 Answers 2


You've noticed the global flip stabilizer $X_1X_2X_3$. You can also notice that the $Z$ parity of any two bits always agrees: There is no amplitude on terms like $|001\rangle$ where the second and third bits have different parities. So you also have parity stabilizers $Z_1Z_2$ and $Z_2Z_3$. This is a three-qubit state, and we've listed three independent stabilizers, so we're done: every other stabilizer is the product of a subset of these stabilizers. For example, $Z_1Z_3=(Z_1Z_2)(Z_2Z_3)$.


You can use software tools. For example, stim.Tableau.from_state_vector:

import stim

ghz_vector = [0] * 8
ghz_vector[0b_000] = 0.5**0.5
ghz_vector[0b_111] = 0.5**0.5

t = stim.Tableau.from_state_vector(ghz_vector, endian='little')

print("Stabilizer generators are:")
for k in range(len(t)):
Stabilizer generators are:

Under the hood what stim is doing is building a circuit to uncompute the state:

  1. Find a non-zero amplitude and use X gates to move it to the start of the vector. (GHZ state already has a non-zero amplitude at the start.)

  2. While there is another non-zero amplitude in the vector:

    • Use CNOT gates to move the second non-zero amplitude to the second entry of the vector (CNOTs instead of NOTs so that the first entry doesn't move).
    • Use S gates on the least significant qubit until the first and second entries have the same phase.
    • Use a Hadamard gate on the least significant qubit to destructively interfere the second entry to 0. Assuming the input was a stabilizer state, this will cut the number of non-zero amplitudes exactly in half.
  3. The accumulated circuit $C$ is now a Clifford circuit that uncomputes the states. It maps the stabilizers of the state to single-qubit stabilizers $Z_q$. Running it backwards maps each $Z_q$ back to a stabilizer. The stabilizers are $C^{-1} Z_q C$ for each qubit $q$.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.