Hi, I am trying to simulate quantum circuits in my school project. I’ve had difficulties with understanding the documentation as I still have no certainty on which is the best approach in a case that we have N qubits, and I wish to operate on each qubit with various operators.
Next I will present a couple of different methods inspired by the documentation code examples. The test case will be a simple N=2 circuit. For the sake of simplicity, let us use only rotation operators. The example circuit will consist of a total of four operators, two operators for each qubit. First operation will rotate the state to some other state, but the following operator should rotate it back to the initial state for debugging purposes.
The first method is using the contraction operators:
using ITensors, ITensorMPS
let
layer1 = ITensor[]
s1 = siteinds("Qubit", 2)
states1 = ["Up" for n=1:2]
psi1 = MPS(s1, states1)
psi0 = MPS(s1, states1)
layer1 = op("Rx", s1[1], θ=π/5)*op("Ry", s1[2], θ=π/5)+op("Rx", s1[1], θ=-π/5)*op("Ry", s1[2], θ=-π/5)
psi1 = apply(layer1, psi1)
normalize!(psi1)
orthogonalize!(psi1,1)
@show abs(inner(psi1, psi0))^2
end
The result will be \approx 0.988977
As the probability was not 1 even for this rather simple test case, I decided to test another approach. However, this does not actually form a MPO.
The second method simply appends the operators:
using ITensors, ITensorMPS
let
layer2 = ITensor[]
s2 = siteinds("Qubit", 2)
states2 = ["Up" for n=1:2]
psi2 = MPS(s2, states2)
psi0 = MPS(s2, states2)
push!(layer2, op("Rx", s2[1], θ=π/5))
push!(layer2, op("Ry", s2[2], θ=π/5))
push!(layer2, op("Rx", s2[1], θ=-π/5))
push!(layer2, op("Ry", s2[2], θ=-π/5))
psi2 = apply(layer2, psi2)
normalize!(psi2)
orthogonalize!(psi2,1)
@show abs(inner(psi2, psi0))^2
end
Now the probability is exactly correct, i.e. 1.0.
I tried a third method using OpSum
, but could not figure out how to sum operators that require parameters in their definitions. This approach would create a MPO.
Questions:
-
Are the two first methods I provided equivalent? There is a difference in the inner product, but is it only due to the fact that the first example uses a MPO, which leads to some numerical errors?
-
Is there a way to use the second method, but still create a MPO from the list of operators? Unfortunately, I could not find such a MPO constructor from the documentation.
-
Is it possible to use the third method, i.e. the
OpSum
feature for these purposes? If so, what is the syntax of adding operators with parameters toOpSum
? -
In case that I would like to play with circuits of N=100 or more, and use multiple different gates, possibly even two qubit gates, what approach would you suggest me to use? The second option, however, probably does not allow to vary the bond dimension, as the operator is not a MPO. Naturally the efficiency and speed is highly important factor in these larger tests, which means (to my understanding) that a MPO should be formed for the circuit.
Thanks in advance!