Work with Observables
This guide covers direct manipulation of Observable
objects.
Manually Evolve an Observable
While the run()
method is the easiest way to perform a simulation,
you can also apply gate transformations directly to an Observable
object.
This can be useful for debugging or custom simulation flows.
Warning
Due to Python overhead, using Observable
apply methods instead of running a circuit can be up to \(1000\) times slower.
Note that you must apply the gates in reverse order to match the definition of Heisenberg evolution.
# Start with a simple Z observable on the first of two qubits
obs = Observable("ZI")
print(f"Initial observable: {obs}")
# Evolve the observable backward through a CNOT gate
# Note: control and target are for the forward circuit, but applied in reverse
obs.apply_cx(0, 1)
print(f"After CX(0,1): {obs}")
# Evolve backward through an H gate on qubit 0
obs.apply_clifford(CliffordGate.H, 0)
print(f"After H(0): {obs}")
Manage Observable Complexity
When an observable is evolved, the number of Pauli terms it contains can grow. You can manually truncate an observable to keep only the most significant terms. The following example keeps only the term with the largest coefficient.
obs = Observable([PauliTerm("II", 0.999), PauliTerm("ZZ", 0.001)])
truncator = CoefficientTruncator(0.01)
obs.truncate(truncator)
Note
See Manage Simulation Complexity, for more information on Truncator
.