There is no option to sample the final Pauli frame exposed to stim's python API (as of 1.18). The closest you can get is to add measurement operations at the end of the circuit, which will be flipped if the Pauli frame anticommutes with the measurement basis.
You could alternatively consider using stim.TableauSimulator
, which doesn't have a pauli frame but does give you magical access to the underlying state. For example, you can use stim.TableauSimulator.peek_observable_expectation
.
In the underlying C++ API what you want is possible, via directly working with stim::FrameSimulator
:
#include "stim.h"
void sample_final_frame(const stim::Circuit &circuit) {
size_t shots = 256;
size_t max_lookback = 1000000;
auto rng = stim::externally_seeded_rng();
stim::FrameSimulator frame_sim(
circuit.count_qubits(),
shots,
max_lookback,
rng);
frame_sim.reset_all_and_run(circuit);
// X errors now at frame_sim.x_table[qubit_index][shot_index]
// Z errors now at frame_sim.z_table[qubit_index][shot_index]
// Y = X*Z
...
}
One thing that might complicate whatever you were planning to use the frame for, is that Stim always partially randomizes the Pauli frame when collapsing operations are performed. For example, applying an R
operation doesn't clear the Pauli frame. Instead, it randomly sets the frame to I or Z. This is how the Heisenberg uncertainty relationship between anticommuting observables is enforced by the frame simulator. The Pauli frame isn't just affected by errors, it's also affected by these sorts of anticommutation effects.