# When does a channel between two error correcting codes preserve logical information?

I am trying to understand when a quantum channel preserves (part of) the information stored in an error correction code.

Take some $$[[n, k, d]]$$ quantum code with stabilizer set $$\mathcal{S}$$. The codewords are the following set of states

$$\{\vert\psi\rangle: \forall S\in \mathcal{S}, S\vert\psi\rangle = \vert\psi\rangle\}$$

Let us apply a quantum channel to the physical qubits such that we get $$n'$$ qubits in the output. Let us now consider some other $$[[n', k', d']]$$ quantum code with stabilizer set $$\mathcal{S}'$$. If I claim that this channel preserves any logical information of the input code then, what conditions must it satisfy?

For a specific example, consider a merge operation in lattice surgery described here. The effect of the physical operations is that they perform a logical $$Z_1Z_2$$ measurement and also transform the logical operators of the input code as follows

$$X_1X_2 \rightarrow X, Z_1 \rightarrow Z, Z_2\rightarrow Z$$

From this, one infers that the logical CPTP map is the isometry $$|0\rangle\langle 00|+|1\rangle\langle 11|$$ if the $$Z_1Z_2$$ measurement is $$+1$$ and $$|0\rangle\langle 01|+|1\rangle\langle 10|$$ if the $$Z_1Z_2$$ measurement is $$-1$$ as shown in the answer. The answer notes that coherences between $$\vert 00\rangle$$ and $$\vert 11\rangle$$ and coherences between $$\vert 01\rangle$$ and $$\vert 10\rangle$$ are preserved - so we have an isometry between those subspaces and the subspaces of the output code.

In this example, how does one know that the logical transformation is in fact an isometry on the eigenspaces of $$Z_1Z_2$$ and that coherences within those eigenspaces are preserved? More generally, how do we see what logical information is preserved during the action of a channel that takes us from one error-correcting code to another?

What you need to show is that the circuit has stabilizer flows mapping the input code's logical qubit observables to the output code's logical qubit observables. In stim terminology, for each input/output observable pair, you need to find a list of measurement indices MEASUREMENT_INDICES that causes

circuit.has_flow(stim.Flow(
input=stim.PauliString(...),
output=stim.PauliString(...),
measurements=MEASUREMENT_INDICES,
), unsigned=True)


to return True. You can then determine if the flow is negated or not, and insert Pauli gates to correct those minus signs (or just classically track which observables are upside down).

Finding the measurement indices can be done automatically.

You can find flow generators for the circuit by making an enormous table of the local flow generators of each individual gate, which are known, and then performing Gaussian elimination on that table in order to filter out all the columns that correspond to Pauli terms inside the circuit.

You can then solve for the list of measurements for a specific desired flow by continuing the Gaussian elimination, in order to solve for how to combine those generators to form the desired flow (or prove it can't be done).

Once you've established the circuit transforms the observables correctly, you then need to move on to showing that it's fault tolerant. When you performed Gaussian elimination to solve for the flow generators of the circuit, you also learned everything you need in order to produce flows between the stabilizers of the codes as well as detectors internal to the transition circuit. These are your checks, and you can start working out how to use the information about whether or not each check passed or failed in order to correct the observables.

This all ends up just being the same thing as normal error correction, except the checks are flows (pauli-product-spread-across-a-circuit) instead of stabilizers (pauli-product-at-one-time). You can still make parity check matrices and compute distances and etc and etc.