I have a program that needs to evaluate several Cirq circuits by using both simulators the Simulator() and DensityMatrixSimulator(). I want to evaluate a circuit that its composed by repeating blocks n=1,2,3,..., so the pseudocode for evaluation looks like this:

for n in some range:

n=1 -> Evaluate block and employ simulate_expectation_values() method of the simulators

n=2 -> Evaluate block+block and employ simulate_expectation_values() method of the simulators

n=3 -> Evaluate block+block+block and employ simulate_expectation_values() method of the simulators


This is highly inefficient as every time I evaluate for a fixed n, the circuit is repeated from the beginning until it reaches n-blocks depth, and I get the expectation values. In real hardware, of course the circuit depth is determined by the time when measurements take place. But at the simulation level, is there a way to perform the above operations in a more efficient way? This means to perform the simulation over all "n"s values at once, and get the expectation values corresponding to each of the n circuit depths without the need to explicitly evaluate the outer loop, and thus, avoiding starting from the beginning on each iteration.


1 Answer 1


cirq.Simulator supports this behavior via simulate_moment_steps and directly calling expectation_value_from_state_vector on each observable:

qubit = cirq.GridQubit(0, 0)
# Rotate the state about Y by an increment of pi/10 per moment
angle = np.pi/10
steps = 10
circuit = cirq.Circuit([cirq.ry(angle)(qubit) for i in range(10)])

# We will compute <Z> after each Ry(pi/10) gate:
observable = cirq.Z(qubit)

simulator = cirq.Simulator()
results = []
for step_result in simulator.simulate_moment_steps(circuit):
    expect = observable.expectation_from_state_vector(step_result.state_vector(), {qubit: 0})
    results.append(np.round(expect.real, 3)) # this is just to make the printout pretty

>> [0.951, 0.809, 0.588, 0.309, -0.0, -0.309, -0.588, -0.809, -0.951, -1.0]

You can adapt this to iterate through a list of observables at each step, as well as use a density matrix simulator instead of just Simulator.

  • 1
    $\begingroup$ Thanks a lot! I was actually using the generator as result of the simulate moment steps and compress it to measure only at those moments I am interested into. $\endgroup$ Commented Mar 1, 2023 at 21:44
  • $\begingroup$ Is there a way to calculate dynamical correlations in Cirq? By using the approach above, getting something like $\langle \sigma^z(i)(t_1)\sigma^z(j)(t_2)\rangle$, at two different moments $t_1,t_2$. $\endgroup$ Commented Mar 2, 2023 at 15:23
  • $\begingroup$ I'm not sure - might be worth asking another question on that. One possibility: Time evolve Z_i by constructing the circuit U(t)* Z_i U(t) and then call cirq.unitary to get the full unitary matrix for each t (which just happens to be unitary because Z_i is unitary). Then d o the same for Z_j and compute expectation values by hand in numpy... $\endgroup$
    – forky40
    Commented Mar 2, 2023 at 18:06

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.