# circuit for quantum simulation?

What would be the circuit for operation exp(iθZ⊗Z⊗Z⊗X) by only using CNOTs and single-qubit gates. And How we can improve the circuit to implement the operation exp(iφZ⊗Z⊗X⊗Z ).exp(iθZ⊗Z⊗Z⊗X).Are there are multiple ways to do it?

Try this circuit: How did I come up with this? The shortcut is that I recognised the $$Z\otimes Z\otimes Z\otimes X$$ as the stabilizer of a graph state, and that has certain standard rules for building it: apply a controlled-phase between the place of the $$X$$ and each of the $$Z$$ terms. In other words, if I group those three controlled-phase gates as "$$U$$", then $$U(Z\otimes Z\otimes Z\otimes X)U^\dagger=I\otimes I\otimes I\otimes X,$$ so $$Ue^{i\theta Z\otimes Z\otimes Z\otimes X}U^\dagger=e^{i\theta X_4}=I\otimes I\otimes I\otimes R_X(2\theta)$$ (depending on your convention for what the rotation matrix means.) Also, note that $$U=U^\dagger$$, so inversion is easy.

Now, you actually asked for controlled-nots instead of controlled-phases. We can convert between the two using Hadamards, and you have a fairly arbitrary choice of which qubit will be the target for each of the gates. A particularly efficient version is to make the bottom qubit the target every time.

If you didn't have that shortcut, how might you have gone about constructing this? My first reaction was to look at the $$Z\otimes Z\otimes Z\otimes X$$, and apply Hadamard to the last qubit, so that you get $$Z\otimes Z\otimes Z\otimes Z$$. What does this observable detect? The parity of the number of 1s in a state. So, if you can find a circuit that computes the parity of the number of bits, you're effectively calculating the value of that observable onto a single qubit, so single qubit gates can add the phase that you need, and then you can uncompute the value. Controlled-nots are great at computing the parity of bit values.

As for your last question, for any Hamiltonian $$H$$, $$e^{i\theta H}e^{i\phi H}=e^{i(\theta+\phi)H}$$ so instead of running your circuit twice, you only run it once, with an altered value of the phase rotation.

You can use a Suzuki-trotter approximation to your Hamiltonian $$e^{i\theta ZZZX}$$ using two-qubit gates as mentioned in Qiskit's operator-flow docs. Below is a sample code to perform the same (Ref).

def compute_U_trot(H, time, trotter_steps, order=1):
"""
Apply the Suzuki-Trotter approximation to the Hamiltonian H to
compute a trotterized unitary time evolution operator.

"""

U_trot = Suzuki(trotter_steps, order=order).convert(time * H)
return U_trot

def convert_U_trot_to_qc(U_trot):
"""
Convert the U_trot ComposedOp object returned by compute_U_trot()
to a bare quantum circuit.
"""

qc_trot = PauliTrotterEvolution().convert(U_trot)
return (
qc_trot.to_circuit().decompose().decompose()
)  # add decompose methods so gates are not abstracted unitary blocks

H = PauliSumOp(SparsePauliOp(["ZZZX",],[1]))

time_param = Parameter("θ")
trotter_steps = 1

# Compute unitary time operator
U_trot_params = compute_U_trot(H, time_param, int(trotter_steps))

# Convert to trotterized unitary to circuit
qc_trot = convert_U_trot_to_qc(U_trot_params)


which gives the following circuit:

The other hamiltonians can be implemented in the same way.